实验目的与内容
实验目的
- 实现SLR(1)分析的语义分析与中间代码生成程序设计原理:
- 深入了解SLR(1)分析方法,以实现对源代码的语义分析。
- 设计和实现编译器前端,包括语法分析和中间代码生成阶段。
- 掌握语法制导的基本概念:
- 理解语法制导翻译的基本理念和原则。
- 利用语法规则引导语义分析,确保编译器能够准确地理解源代码结构。
- 研究目标代码结构分析的基本方法:
- 学习目标代码的结构分析技术,以确保生成的中间代码在后续阶段能够被正确翻译为目标代码。
- 掌握如何优化目标代码结构,以提高最终程序的执行效率。
- 实现赋值语句语法制导生成四元式的基本原理和方法:
- 理解赋值语句的语法结构,并通过语法制导方法生成对应的四元式。
- 考虑语义信息,确保生成的中间代码能够准确地反映源代码的语义。
- 完善语法分析和语义分析过程:
- 设计和实现强大的语法分析器,确保对源代码进行准确的结构分析。
- 在语义分析阶段,处理语法制导的翻译,生成相应的中间代码。
实验内容
以专题1词法分析程序的输出为语法分析的输入,完成以下描述赋值语句SLR(1)文法的语义分析及中间代码四元式的过程,实现编译器前端。
G[S]: S→V=E
E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
V→i
实验要求
设计说明
终结符号i为用户定义的简单变量,即标识符的定义。重点解决SLR(1)分析表构造,赋值语句文法的改写和语义动作的添加。解决编译程序总体结构理解问题,理解语法制导翻译过程的基本概念和实现方法,理解编译器前端的组成。
设计要求
- 构造文法的SLR(1)分析表,设计语法制导翻译过程,给出每一产生式对应的语义动作;
- 设计中间代码四元式的结构;
- 输入串应是词法分析的输出二元式序列,即某赋值语句“专题1”的输 出结果,输出为赋值语句的四元式序列中间文件;
- 以交互界面的形式给出SLR(1)分析过程,要求包括符号栈、状态栈、输入串等的变化情况以及当前完成的动作。
- 设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。
- 选做:考虑根据文法自动构造SLR(1)分析表,并添加到你的程序中。
实验过程
完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <string>
#include <list>
#include <stack>
#include <iostream>
#include <algorithm>
#include<cstring>
using namespace std;
typedef struct s
{
int finish = 0; // Whether finished
int tag = 3; // Current position of the dot
string str;
} sentence;
typedef struct
{
int I; // Current state
char Vt; // Terminal symbol
char tag; // r or s
int action; // Action
} act;
typedef struct
{
int I; // Current state
char Vn; // Non-terminal symbol
int next_I; // Transition state
} go;
typedef struct
{
int number; // Number
list<sentence> l;
} I; // State
typedef struct
{
char op;
char arg1;
char arg2;
char result;
} siyuanshi;
typedef struct
{
char name;
string value; // Place
} var; // Variable
list<I> DFA; // State set
list<char>* First; // FIRST set
list<char>* Follow; // FOLLOW set
list<act> ACTION; // ACTION[i][j]
list<go> GOTO; // GO[i][j]
list<char> Vt; // Terminal symbols set
list<char> Vn; // Non-terminal symbols set
char input[100]; // Read input from lexical analysis
void readfile()
{
cout << "-------------------------------------------------------" << endl;
cout << "Read file to get input statements:" << endl;
FILE* fp;
char buf[1000];
if ((fp = fopen("./test2.txt", "r")) != NULL) {
while (fgets(buf, 1000, fp) != NULL)
{
int len = strlen(buf);
printf("%s", buf);
int flag = 0;
for (int i = 0; i < len; i++) {
if (buf[i] == '(' && flag == 0) {
flag = 1; // Recognize symbol
for (int j = i + 1; j < len; j++) {
if (buf[j] == ',') {
input[strlen(input)] = buf[j + 1];
i = j + 1;
break;
}
}
}
else if (flag == 1 && buf[i] == ')') {
flag = 0;
}
}
}
}
input[strlen(input)] = '#';
fclose(fp);
cout << endl;
cout << endl << "Input string: " << input << endl << endl;
}
int S[100]; // Analysis stack
int S_top = 0; // Analysis stack top
char T[100]; // Symbol stack, top is the same as the analysis stack
string value[100]; // Store symbol attributes
list<siyuanshi> L_sys; // Quadruple
list<int> sys; // States set that generate quadruples
list<var> V; // Variable table
int result_count = 0;
string G[11] = { "S->A", "A->V=E", "E->E+T", "E->E-T", "E->T", "T->T*F", "T->T/F", "T->F", "F->(E)", "F->i", "V->i" };
act getACTION(int i, char b)
{
char c = b;
if (b >= 'a' && b <= 'z')
b = 'i';
list<act>::iterator it;
for (it = ACTION.begin(); it != ACTION.end(); it++)
{
if (it->I == i && it->Vt == b)
{
return *it;
}
}
return { 0,0,0,0 }; // ERROR
}
int getGOTO(int i, char b)
{
list<go>::iterator it;
for (it = GOTO.begin(); it != GOTO.end(); it++)
{
if (it->I == i && it->Vn == b)
return it->next_I;
}
return -1; // ERROR
}
char newTemp()
{
char c = 'A';
result_count++;
return c + result_count - 1;
}
void SLR()
{
int V_num = 0; // Symbol table
int index = 0;
S[0] = 0; // Initialize
cout << "Analysis stack: (| | contains attributes of non-terminal symbols)" << endl;
while (getACTION(S[S_top], input[index]).tag != 'r' || getACTION(S[S_top], input[index]).action != 0) // acc
{
if (getACTION(S[S_top], input[index]).tag == 0) // ERROR
{
cout << "Error!" << endl; // Error handling
return;
}
else if (getACTION(S[S_top], input[index]).tag == 's')
{ // push
S[S_top + 1] = getACTION(S[S_top], input[index]).action; // Push operation
T[S_top + 1] = input[index];
value[S_top + 1] = input[index];
S_top++;
index++; // Advance(); read the next symbol
}
else if (getACTION(S[S_top], input[index]).tag == 'r')
{
char arg1, arg2, result; // Quadruple
int i = getACTION(S[S_top], input[index]).action; // Production to be reduced
string str = "";
for (int j = 0; j < G[i].length() - 3; j++)
{
// pop operation
if (value[S_top] != "(" && value[S_top] != ")")
{
string ss = "";
ss += value[S_top];
ss += str;
str = string(ss);
}
if (j == 0)
if (value[S_top].length() == 1) // Single symbol
arg1 = value[S_top][0];
else // Look up the table, find the symbol
{
for (list<var>::iterator v = V.begin(); v != V.end(); v++)
{
if (v->value == value[S_top])
{
arg1 = v->name;
break;
}
}
}
if (j == 2)
if (value[S_top].length() == 1)
arg2 = value[S_top][0];
else
for (list<var>::iterator v = V.begin(); v != V.end(); v++)
{
if (v->value == value[S_top])
{
arg2 = v->name;
break;
}
}
S[S_top] = -1;
T[S_top] = 0;
value[S_top] = "";
S_top--;
}
for (list<int>::iterator ii = sys.begin(); ii != sys.end(); ii++) // Generate quadruple
if (i == *ii)
{
result = newTemp();
V.push_back({ result, str });
L_sys.push_back({ G[i][4], arg1, arg2, result });
break;
}
// push
S[S_top + 1] = getGOTO(S[S_top], G[i][0]);
T[S_top + 1] = G[i][0];
value[S_top + 1] = str; // Attribute transfer
S_top++;
}
for (int tt = 0; tt <= 15; tt++)
{
if (tt <= S_top)
if (S[tt] >= 10)
cout << S[tt] << " ";
else
cout << S[tt] << " ";
else
cout << " ";
}
for (int tt = 0; tt <= S_top; tt++)
{
if (tt <= S_top)
{
cout << T[tt] << " ";
if (isupper(T[tt]))
cout << "|" << value[tt] << "| ";
}
else
cout << " ";
}
cout << endl;
}
cout << endl << "Match successful!" << endl;
cout << endl << "Quadruples:" << endl;
for (list<siyuanshi>::iterator s = L_sys.begin(); s != L_sys.end(); s++)
{
cout << '(' << s->op << "," << s->arg1 << "," << s->arg2 << ',' << s->result << ')' << endl;
}
}
void print(sentence s)
{
int r;
cout << " ";
for (r = 0; r < s.str.length(); r++)
if (r == s.tag)
cout << "·" << s.str[r];
else
cout << s.str[r];
if (r == s.tag)
cout << "·";
cout << endl;
}
void find(char ch, int tag_Vn)
{
for (int qq = 0; qq < 11; qq++)
{
if (ch == G[qq][0])
{
if (G[qq][3] >= 'A' && G[qq][3] <= 'Z')
if (G[qq][3] == ch) // Avoiding infinite loop and repeated searches
;
else
find(G[qq][3], tag_Vn);
else
{
int tag = 0;
for (list<char>::iterator i = First[tag_Vn].begin(); i != First[tag_Vn].end(); i++)
{
if (*i == G[qq][3])
{
tag = 1;
break;
}
}
if (tag == 0)
First[tag_Vn].push_back(G[qq][3]);
}
}
}
}
int findVn(char c)
{
int tag = -1;
for (list<char>::iterator i = Vn.begin(); i != Vn.end(); i++)
{
tag++;
if (c == *i)
return tag;
}
return -1;
}
void scan() // Construct symbol sets
{
for (int i = 0; i < 11; i++)// Grammar length
{
for (int j = 0; j < G[i].length(); j++)
{
if (j == 1 || j == 2)
continue;
if (isupper(G[i][j]))
{
if (find(Vn.begin(), Vn.end(), G[i][j]) == Vn.end())
Vn.push_back(G[i][j]);
}
else
{
if (find(Vt.begin(), Vt.end(), G[i][j]) == Vt.end())
Vt.push_back(G[i][j]);
}
}
}
Vt.push_back('#');
First = new list<char>[Vn.size()];
int tag_Vn = -1;
for (list<char>::iterator ch = Vn.begin(); ch != Vn.end(); ch++)
{
tag_Vn++;
for (int qq = 0; qq < 11; qq++)
{
if (*ch == G[qq][0])
{
if (G[qq][3] >= 'A' && G[qq][3] <= 'Z')
{
find(G[qq][3], tag_Vn);
}
else
{
First[tag_Vn].push_back(G[qq][3]);
}
}
}
}
Follow = new list<char>[Vn.size()];
Follow[0].push_back('#');
int follow_sum = 0; // Follow set total quantity
int previous_sum = -1; // Previous total
while (follow_sum != previous_sum)
{
for (int i = 0; i < 11; i++)
{
for (int j = 3; j < G[i].length() - 1; j++)
{
if (isupper(G[i][j]))
if (!isupper(G[i][j + 1])) // Terminal symbol
{
int tag = 0;
for (list<char>::iterator ii = Follow[findVn(G[i][j])].begin(); ii != Follow[findVn(G[i][j])].end(); ii++)
{
if (*ii == G[i][j + 1])
{
tag = 1;
break;
}
}
if (tag == 0)
Follow[findVn(G[i][j])].push_back(G[i][j + 1]);
}
else // Non-terminal symbol
{
for (list<char>::iterator ii = Follow[findVn(G[i][j + 1])].begin(); ii != Follow[findVn(G[i][j + 1])].end(); ii++)
{
if (find(Follow[findVn(G[i][j + 1])].begin(), Follow[findVn(G[i][j + 1])].end(), *ii) == Follow[findVn(G[i][j + 1])].end()) // Not repeated
Follow[findVn(G[i][j])].push_back(*ii);
}
}
}
if (isupper(G[i][G[i].length() - 1]))
for (list<char>::iterator ii = Follow[findVn(G[i][0])].begin(); ii != Follow[findVn(G[i][0])].end(); ii++)
{
if (find(Follow[findVn(G[i][G[i].length() - 1])].begin(), Follow[findVn(G[i][G[i].length() - 1])].end(), *ii) == Follow[findVn(G[i][G[i].length() - 1])].end()) // Not repeated
Follow[findVn(G[i][G[i].length() - 1])].push_back(*ii);
}
}
previous_sum = follow_sum;
follow_sum = 0;
for (int ii = 0; ii < Vn.size(); ii++)
{
follow_sum += Follow[ii].size();
}
}
list<char>::iterator iter;
cout << "Terminal symbols set: ";
for (iter = Vt.begin(); iter != Vt.end(); iter++)
{
cout << *iter;
}
cout << endl;
cout << "Non-terminal symbols set: ";
for (iter = Vn.begin(); iter != Vn.end(); iter++)
{
cout << *iter;
}
cout << endl;
int pp;
cout << "FIRST" << endl;
for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
{
cout << *iter << " ";
for (list<char>::iterator ch = First[pp].begin(); ch != First[pp].end(); ch++)
{
cout << *ch << " ";
}
cout << endl;
}
cout << "FOLLOW" << endl;
for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
{
cout << *iter << " ";
for (list<char>::iterator ch = Follow[pp].begin(); ch != Follow[pp].end(); ch++)
{
cout << *ch << " ";
}
cout << endl;
}
}
I closure(I& dfa)
{
list<sentence>::iterator iter;
for (iter = dfa.l.begin(); iter != dfa.l.end(); iter++)
{
if ((iter->tag <= iter->str.length()))
if ((iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z'))
{
for (int tt = 0; tt < 11; tt++) // Find the corresponding production
{
if (iter->str[iter->tag] == G[tt][0])
{
int q = 0;
list<sentence>::iterator it;
sentence x;
x.str = G[tt];
for (it = dfa.l.begin(); it != dfa.l.end(); it++)
{
if ((it->str == x.str) && (it->tag == x.tag))
{
q = 1;
break;
}
}
if (q == 0)
{
dfa.l.push_back(x);
}
}
}
}
}
return dfa;
}
int compare(I a, I b) // Whether equal
{
if (a.l.size() != b.l.size())
return 1;
else
{
for (list<sentence>::iterator iii = a.l.begin(), jjj = b.l.begin(); iii != a.l.end() || jjj != b.l.end(); iii++, jjj++)
if (iii->str != jjj->str || iii->tag != jjj->tag) // Check if equal
{
return 1;
}
}
return 0;
}
void table()
{
int num = 0;
sentence first; // Starting symbol
first.str = G[0];
I L;
L.number = 0;
L.l.push_back(first);
DFA.push_back(L);
list<I>::iterator dfa;
for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
{
list<sentence>::iterator iter;
closure(*dfa);
for (iter = dfa->l.begin(); iter != dfa->l.end(); iter++) // Process each right part of the production in the state
if (iter->finish == 0)
{
I C; // New state
C.number = DFA.size();
if (iter->tag < iter->str.length()) // Not completed yet
{
sentence s;
s.str = iter->str;
if (iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z')
{
GOTO.push_back({ dfa->number,iter->str[iter->tag],C.number });
}
else
{
ACTION.push_back({ dfa->number,iter->str[iter->tag],'s',C.number });
}
s.tag = iter->tag + 1;
iter->finish = 1;
C.l.push_back(s);
list<sentence>::iterator i;
for (i = iter, i++; i != dfa->l.end(); i++)
if (i->str[i->tag] == iter->str[iter->tag])
{
s.str = i->str;
s.tag = i->tag + 1;
i->finish = 1;
C.l.push_back(s);
}
int judge = 0, count = 0;
for (list<I>::iterator ii = DFA.begin(); ii != DFA.end(); ii++, count++) // Check for duplicates
{
judge = compare(*ii, closure(C)); // Modify C
if (judge == 0)
break;
}
if (judge == 0)
{
if (iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z')
{
GOTO.pop_back();
GOTO.push_back({ dfa->number,iter->str[iter->tag], count });
}
else
{
ACTION.pop_back();
ACTION.push_back({ dfa->number,iter->str[iter->tag],'s',count });
}
}
else
DFA.push_back(C);
}
else // Already completed
{
int cc = 0, tt;
for (tt = 0; tt < 11; tt++)
{
if (iter->str == G[tt])
break;
}
for (list<char>::iterator c = Vn.begin(); c != Vn.end(); c++, cc++)
if (*c == iter->str[0])
break;
for (list<char>::iterator c = Follow[cc].begin(); c != Follow[cc].end(); c++)
{
ACTION.push_back({ dfa->number,*c,'r',tt }); // Corresponding to the jth production
for (int ss = 3; ss < G[tt].length(); ss++) // Find the production corresponding to the four-element
if (G[tt][ss] == '+' || G[tt][ss] == '-' || G[tt][ss] == '*' || G[tt][ss] == '/')
{
sys.push_back(tt);
}
}
}
}
}
num = 0;
for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
{
cout << "State " << num++ << ":" << endl;
for (list<sentence>::iterator iii = dfa->l.begin(); iii != dfa->l.end(); iii++)
{
cout << " ";
print(*iii);
}
}
cout << endl;
int kkk = 0;
for (list<go>::iterator g = GOTO.begin(); g != GOTO.end(); g++)
{
cout << "GOTO(" << g->I << ", " << g->Vn << ") = " << g->next_I<<" ";
kkk++;
if (kkk % 4 == 0) {
cout << endl;
}
}
cout << endl << endl;
kkk = 0;
for (list<act>::iterator a = ACTION.begin(); a != ACTION.end(); a++)
{
cout << "ACTION(" << a->I << ", " << a->Vt << ") = " << a->tag << a->action << " ";
kkk++;
if (kkk % 4 == 0) {
cout << endl;
}
}
cout << endl;
}
int main()
{
readfile();
scan();
table();
SLR();
cout << "---------------------21281157 hxd------------------------" << endl;
return 0;
}
测试
Test1:
示例如下:
DFA状态集:
SLR分析表:
SLR文法分析和四元式构造过程: