这学期的编译原理终于学完了,不愧是号称最难的科目。要用C++从头到尾实现一下小型编译器,还真不容易啊。不过总算是做完了。

首先上文法,这个文法是根据上一篇博客简化的,但还是有一点问题的,暂时发现有一个地方不符合LR1的规则(函数的返回类型如果是int就会报错)。

有了文法就可以生成LR1分析表了,如图所示,一共有187个项目集族,代码跑了2分50秒才出结果,要不是我优化了一个下午,剪掉了一些不必要的循环,以及把一个o(n)的改成了lg的,大概要跑10分钟吧。

具体的优化在代码中有注释。

生成的LR(1)表存到文件中,用err表示空格,便于从文件再读到程序中,如图所示:

接下来是输入程序:

转成Token,如果是ID或则NUM类型的,还需要存下对应的值。

下面的就是分析过程和“文本格式的语法树”了

同时dfs语法树生成了四元式:

代码:

  1 #include <map>
  2 #include <set>
  3 #include <list>
  4 #include <ctime>
  5 #include <queue>
  6 #include <stack>
  7 #include <string>
  8 #include <vector>
  9 #include <iomanip>
 10 #include <fstream>
 11 #include <sstream>
 12 #include <iostream>
 13 using namespace std;
 14 #define rep(i,a,n) for(int i=a;i<n;i++)
 15 #define per(i,a,n) for(int i=n-1;i>=a;i--)
 16 #define all(x) (x).begin(),(x).end()
 17 typedef pair<string, vector<string>> Production;        //产生式
 18 const int WIDTH = 16;    //setw(WIDTH)
 19 // head
 20
 21 struct Project {        //项目集
 22     string left;
 23     vector<string> right;
 24     set<string> expect;
 25
 26     const bool operator<(const Project &p) const {
 27         if (left < p.left) return true;
 28         if (left > p.left) return false;
 29         if (right < p.right) return true;
 30         if (right > p.right) return false;
 31         if (expect < p.expect) return true;
 32         return false;
 33     }
 34
 35     const bool operator==(const Project &p) const {
 36         if (left == p.left && right == p.right && expect == p.expect) return true;
 37         return false;
 38     }
 39 };
 40
 41 namespace project {    //产生项目集族
 42     set<string> terminal;        //终结符
 43     set<string> not_terminal;    //非终结符
 44     set<string> all_symbol;        //所有的符号
 45     vector<string> sss;            //所有的符号
 46     map<string, int> Hash;        //符号哈希
 47     vector<Production> vp;        //所有的产生式,加·前
 48     set<Production> sp;            //所有的项目集,加·后
 49
 50     void PROJECT() {
 51         ifstream fin("C:\\Users\\Flowersea\\Desktop\\Grammar.txt");
 52         string a, b;
 53         vector<string> c;
 54         while (fin >> a >> b) {
 55             not_terminal.insert(a);
 56             string str;
 57             getline(fin, str);
 58             stringstream ss;
 59             ss.str(str);
 60             c.clear();
 61             while (ss >> str) {
 62                 c.push_back(str);
 63                 int fg = 0;
 64                 rep(i, 0, str.size()) {
 65                     if (!(str[i] >= 'a' && str[i] <= 'z' || str[i] == '_')) {    //文法中非终结符都是小写字母和下划线组成的
 66                         fg = 1;
 67                         break;
 68                     }
 69                 }
 70                 if (fg) terminal.insert(str);    //如果含有小写字母和下划线以外的符号就是终结符
 71                 else not_terminal.insert(str);    //否则是非终结符
 72             }
 73             vp.push_back(Production(a, c));
 74         }
 75         terminal.insert("#");
 76         not_terminal.erase("program'");        //删掉program'
 77         all_symbol.insert(all(terminal));
 78         all_symbol.insert(all(not_terminal));
 79         for (auto it : terminal) sss.push_back(it);
 80         for (auto it : not_terminal) sss.push_back(it);    //sss其实是为了输出lr1表的表头
 81         rep(i, 0, sss.size()) Hash[sss[i]] = i;
 82         for (auto it : vp) {
 83             a = it.first, c = it.second;
 84             rep(i, 0, c.size() + 1) {
 85                 vector<string> d = c;
 86                 d.insert(d.begin() + i, ".");
 87                 sp.insert(Production(a, d));
 88             }
 89         }
 90     }
 91
 92     void main() {
 93         PROJECT();
 94     }
 95 }
 96
 97 namespace lr1 {    //生成lr表
 98     using namespace project;
 99
100     vector<set<Project>> vsp(1);    //项目集族
101     string lr1[1000][1000];        //lr1表
102     int n, m;                    //n行,m列
103
104     set<string> FIRST(vector<string> X) {    //求FIRST集族
105         set<string> res;
106         if (terminal.find(X[0]) != terminal.end()) {
107             res.insert(X[0]);    //如果是终结符,直接insert返回
108             return res;
109         }
110         else {
111             rep(j, 0, vp.size()) {    //遍历所有的产生式
112                 if (vp[j].first == X[0]) {
113                     if (terminal.find(vp[j].second[0]) != terminal.end())    //如果第一个是终结符
114                         res.insert(vp[j].second[0]);                            //插入到res中
115                     else {
116                         set<string> t = FIRST(vp[j].second);                    //否则递归求FIRST集
117                         res.insert(all(t));
118                     }
119                 }
120             }
121         }
122         return res;
123     }
124
125     set<Project> GO(set<Project> I, string X) {    //GO函数
126         set<Project> J;
127         for (auto it : I) {
128             vector<string> vs = it.right;
129             auto pos = find(all(vs), ".");
130             if (pos == vs.end() - 1) continue;    //如果·是最后一个,continue
131             if (*(pos + 1) == X) {
132                 swap(*pos, *(pos + 1));            //交换·和后面的一个字符串
133                 J.insert(Project{ it.left, vs, it.expect });
134             }
135         }
136         return J;
137     }
138
139     set<Project> CLOSURE(set<Project> I) {        //求closure
140         while (1) {
141             bool update = false;                    //判断此次循环是否有更新
142             for (auto it : I) {
143                 vector<string> B = it.right;
144                 auto pos = find(all(B), ".");        //找到·的位置
145                 if (pos == B.end() - 1) continue;    //如果·是最后一个,continue
146                 string c = *(pos + 1);                //c等于·后面的字符
147                 if (terminal.find(c) != terminal.end()) continue;    //如果c是终结符,continue
148                 B.erase(B.begin(), pos + 2);            //删掉·后面的一个字符之前的所有字符,包括它自己
149                 string last;                            //为了剪枝,记录上一次求FIRST集的第一个字符串
150                 for (auto ite : it.expect) {
151                     B.push_back(ite);                //把expect插入到B的后面
152                     if (last == B[0]) continue;        //如果B[0]和上次的last一样,就不求了,因为文法中没有空产生式
153                     else last = B[0];
154                     set<string> First = FIRST(B);    //求B的FIRST集
155                     B.pop_back();
156                     for (auto it1 : sp) {
157                         if (it1.first == c && it1.second[0] == ".") {    //找到·开头的
158                             set<string> ss;                                //ss为空,为了二分查找
159                             Project p{ it1.first,it1.second,ss };
160                             auto pos = I.lower_bound(p);                    //查找第一个大于等于p的位置
161                             if (pos != I.end() && (*pos).left == it1.first && (*pos).right == it1.second) {    //如果pos指向的first,second符合
162                                 p = *pos;
163                                 I.erase(p);                        //因为不能直接插入,所以需要先删除在插入
164                                 p.expect.insert(all(First));
165                                 I.insert(p);
166                             }
167                             else {
168                                 update = true;        //插入了新的一项,所以update为true。经过测试发现只更新expext可以不用设置update为true
169                                 I.insert(Project{ it1.first, it1.second, First });
170                             }
171                         }
172                     }
173                 }
174             }
175             if (!update) break;    //如果没更新,跳出循环
176         }
177         return I;
178     }
179
180     void LR1() {
181         for (auto it : sp) {        //先插入第一条program' -> program
182             if (it.first == "program'" && it.second[0] == ".") {
183                 set<string> ss;
184                 ss.insert("#");
185                 vsp[0].insert(Project{ it.first,it.second, ss });
186                 break;
187             }
188         }
189         vsp[0] = CLOSURE(vsp[0]);    //然后求第一个项目集的闭包
190         rep(i, 0, vsp.size()) {
191             time_t t = time(0);        //为了在控制台显示每个项目集计算的时间,debug
192             char tmp[64];
193             strftime(tmp, sizeof(tmp), ": %X", localtime(&t));
194             cout << i;
195             puts(tmp);
196             //规约
197             for (auto it : vsp[i]) {
198                 int len = it.right.size();
199                 if (it.right[len - 1] == ".") {        //如果最后一个字符串是·,就可以规约了
200                     it.right.erase(it.right.end() - 1);        //删除那个·
201                     Production p(it.left, it.right);            //构造产生式p
202                     rep(j, 0, vp.size()) {
203                         if (vp[j] == p) {                    //此次循环是为了找到产生式p的编号为j
204                             string t = "r" + to_string(j);    //lr1表
205                             if (j == 0) t = "acc";            //如果是第0条,应该是acc
206                             for (auto its : it.expect)
207                                 lr1[i][Hash[its]] = t;        //填lr1表
208                         }
209                     }
210                 }
211             }
212
213             for (auto X : all_symbol) {                //遍历所有的符号
214                 set<Project> J = GO(vsp[i], X);        //J = GO(I, X)
215                 if (!J.empty()) {                    //如果J不为空
216                     J = CLOSURE(J);                    //求J的闭包
217                     int k;
218                     auto pos = find(all(vsp), J);
219                     if (pos != vsp.end()) {            //如果vsp中已经存在了这个项目集族
220                         k = pos - vsp.begin();        //记下存在的位置
221                     }
222                     else {
223                         k = vsp.size();                //不存在就插入,标号k就是push之前的size
224                         vsp.push_back(J);
225                     }
226
227                     //移进和GOTO
228                     int j = Hash[X];
229                     if (terminal.find(X) != terminal.end())    //如果X为终结符
230                         lr1[i][j] = "s" + to_string(k);        //就移进
231                     else lr1[i][j] = to_string(k);            //否则goto
232                 }
233             }
234         }
235     }
236
237     void PRINT() {    //此函数为了输出项目集族和lr表到文件中
238         ofstream fout("C:\\Users\\Flowersea\\Desktop\\output.out");
239         fout << "      CLOSURE" << endl;
240         rep(i, 0, 20) fout << '-';
241         fout << endl;
242         rep(i, 0, vsp.size()) {
243             fout << i << ":" << endl;
244             set<Project> sp = vsp[i];
245             for (auto it : sp) {
246                 string b;
247                 rep(i, 0, it.right.size()) b += ' ' + it.right[i];
248                 b.erase(0, 1);
249                 string c;
250                 for (auto it : it.expect) c += it + '/';
251                 c.pop_back();
252                 fout << "    " << it.left << " -> "
253                     << b << ", " << c << endl;
254             }
255             rep(i, 0, 20) fout << '-';
256             fout << endl;
257         }
258         fout << endl << endl << endl;
259
260         rep(i, 0, 3) fout << setw(WIDTH) << ' ';
261         fout << "LR(1)分析表" << endl;
262         fout << '|' << endl << '|';
263         fout << setw(WIDTH) << "状态";
264         fout << '|';
265         n = vsp.size();
266         m = sss.size();
267         rep(i, 0, m) {
268             fout << setw(WIDTH) << sss[i];
269             if (i == terminal.size() - 1) fout << '|';
270         }
271         fout << '|' << endl << '|';
272         rep(i, 0, 200) fout << '-';
273         fout << '|' << endl << '|';
274         rep(i, 0, n) {
275             fout << setw(WIDTH) << i;
276             fout << '|';
277             rep(j, 0, m) {
278                 fout << setw(WIDTH) << lr1[i][j];
279                 if (j == terminal.size() - 1) fout << '|';
280             }
281             fout << '|' << endl << '|';
282         }
283         rep(i, 0, 200) fout << '-';
284         fout << '|';
285         fout << endl << endl << endl;
286     }
287
288     void OUT_LR1() {        //输出lr1表到文件中
289         ofstream fout("C:\\Users\\Flowersea\\Desktop\\LR(1).txt");
290         fout << n << " " << m << endl;
291         rep(i, 0, n) {
292             rep(j, 0, m) {
293                 if (lr1[i][j] == "") fout << "err ";        //如果为空,输出err
294                 else fout << lr1[i][j] << ' ';
295             }
296             fout << endl;
297         }
298     }
299
300     void main() {
301         project::main();
302         LR1();
303         PRINT();
304         OUT_LR1();
305     }
306 }
307
308 namespace grammar {
309     using namespace project;
310     struct E {            //E,记录一下信息
311         string place;    //位置
312         vector<pair<int, vector<string>>> code;    //四元式
313         string name;        //变量的name
314         string value;    //常量的value
315         int Begin;
316         int Next;
317         int True;
318         int False;;
319     };
320
321     string lr1[1000][1000];
322     int n, m;
323     int cnt = 0;                //Tree的节点数
324     vector<int> G[1000];        //用邻接表存Tree
325     vector<string> symbol;    //每个节点对应的符号名字
326     vector<E> attr;            //每个节点对用的属性,类型是E
327
328     void IN_LR1() {    //读入lr表
329         ifstream fin("C:\\Users\\Flowersea\\Desktop\\LR(1).txt");
330         fin >> n >> m;
331         rep(i, 0, n) rep(j, 0, m) fin >> lr1[i][j];
332     }
333
334     void MORPHOLOGY() {    //词法分析器
335         ifstream fin("C:\\Users\\Flowersea\\Desktop\\Program.txt");
336         ofstream fout("C:\\Users\\Flowersea\\Desktop\\Token.txt");
337         string keyword[27] = { "main","if","else","int","return","void","while",
338             "=","+","-","*","/","<","<=",">",">=","!=","==",",",";",":","{","}","[","]","(",")" };
339         map<string, int> H;
340         rep(i, 0, 27) H[keyword[i]] = i + 1;
341         string s;
342         while (fin >> s) {
343             rep(i, 0, s.length()) {
344                 if (isalpha(s[i])) {
345                     if (s[i] == 'm' && s[i + 1] == 'a' && s[i + 2] == 'i'
346                         && s[i + 3] == 'n' && !isalnum(s[i + 4])) {
347                         fout << "ID" << endl;
348                         i += 3;
349                     }
350                     else if (s[i] == 'i' && s[i + 1] == 'f' && !isalnum(s[i + 2])) {
351                         fout << "IF" << endl;
352                         i += 1;
353                     }
354                     else if (s[i] == 'e' && s[i + 1] == 'l' && s[i + 2] == 's'
355                         && s[i + 3] == 'e' && !isalnum(s[i + 4])) {
356                         fout << "ELSE" << endl;
357                         i += 3;
358                     }
359                     else if (s[i] == 'i' && s[i + 1] == 'n' && s[i + 2] == 't'
360                         && !isalnum(s[i + 3])) {
361                         fout << "INT" << endl;
362                         i += 2;
363                     }
364                     else if (s[i] == 'r' && s[i + 1] == 'e' && s[i + 2] == 't' && s[i + 3] == 'u'
365                         && s[i + 4] == 'r' && s[i + 5] == 'n' && !isalnum(s[i + 6])) {
366                         fout << "RETURN" << endl;
367                         i += 5;
368                     }
369                     else if (s[i] == 'v' && s[i + 1] == 'o' && s[i + 2] == 'i'
370                         && s[i + 3] == 'd' && !isalnum(s[i + 4])) {
371                         fout << "VOID" << endl;
372                         i += 3;
373                     }
374                     else if (s[i] == 'w' && s[i + 1] == 'h' && s[i + 2] == 'i'
375                         && s[i + 3] == 'l' && s[i + 4] == 'e' && !isalnum(s[i + 5])) {
376                         fout << "WHILE" << endl;
377                         i += 4;
378                     }
379                     else {
380                         string token;
381                         while (isalnum(s[i])) token += s[i++];
382                         i--;
383                         fout << "ID" << ' ' << token << endl;
384                     }
385                 }
386                 else if (isdigit(s[i])) {
387                     int num = 0;
388                     while (isdigit(s[i])) num = num * 10 + s[i++] - '0';
389                     i--;
390                     fout << "NUM" << ' ' << num << endl;
391                 }
392                 else {
393                     if (s[i] == '!') {
394                         fout << "!=" << endl;
395                         i++;
396                     }
397                     else if (s[i] == '=' && s[i + 1] == '=') {
398                         fout << "==" << endl;
399                         i++;
400                     }
401                     else if (s[i] == '<' && s[i + 1] == '=') {
402                         fout << "<=" << endl;
403                         i++;
404                     }
405                     else if (s[i] == '>' && s[i + 1] == '=') {
406                         fout << ">=" << endl;
407                         i++;
408                     }
409                     else {
410                         string t;
411                         t += s[i];
412                         fout << t << endl;
413                     }
414                 }
415             }
416         }
417     }
418
419     void JUDGE() {    //生成语法树
420         ifstream fin("C:\\Users\\Flowersea\\Desktop\\Token.txt");
421         ofstream fout("C:\\Users\\Flowersea\\Desktop\\Analysis.txt");
422
423         vector<pair<string, string>> vs;        //存Token
424         pair<string, string> str;
425         while (fin >> str.first) {
426             if (str.first == "NUM" || str.first == "ID")
427                 fin >> str.second;    //如果是NUM和ID还要读入name或value
428             vs.push_back(str);
429         }
430
431         int a[1000], top = 1;    //a位状态栈,top为栈顶指针
432         a[0] = 0;                                        //初始状态
433         E e;                                                //初始状态
434         vector<pair<string, E>> b{ make_pair("#",e) };    //初始状态
435         vector<pair<string, string>> c = vs;                //初始状态
436         c.push_back(make_pair("#", ""));                    //初始状态
437
438         fout << left << setw(WIDTH / 2) << "";
439         fout << left << setw(WIDTH * 4) << "状态";
440         fout << left << setw(WIDTH * 10) << "符号";
441         fout << right << setw(WIDTH * 7) << "输入串" << endl;
442
443         int id = 1;    //id为行数
444         stack<int> S;    //S同步每一次操作,为了生成Tree
445         while (1) {
446             string temp;
447             rep(i, 0, top) temp += to_string(a[i]) + ' ';
448             fout << left << setw(WIDTH / 2) << id++;
449             fout << left << setw(WIDTH * 4) << temp;
450             string sb, sc;
451             for (auto it : b) sb += ' ' + it.first;
452             sb.erase(0, 1);
453             for (auto it : c) sc += ' ' + it.first;
454             sc.erase(0, 1);
455             fout << left << setw(WIDTH * 10) << sb;
456             fout << right << setw(WIDTH * 7) << sc << endl;    //以上都是为了输出
457
458             string action = lr1[a[top - 1]][Hash[c[0].first]];    //查lr1表
459             if (action == "acc") break;                            //如果是acc表示结束,break
460             if (action == "err") {                                //如果是err表示出错,直接return
461                 cerr << "error" << endl;
462                 return;
463             }
464             if (action[0] == 's') {                                //如果action第一个字符为s,表示移进
465                 action.erase(0, 1);                                //删掉第一个字符
466                 int num = atoi(action.c_str());                    //转成数字
467                 a[top++] = num;                                    //push进栈a
468                 E e;
469                 if (c[0].first == "ID") e.name = c[0].second;    //如果是ID,记下name
470                 else if (c[0].first == "NUM") e.value = c[0].second;    //如果是NUM,记下value
471                 b.push_back(make_pair(c[0].first, e));            //push进栈b
472                 symbol.push_back(c[0].first);                    //push进栈symbol
473                 attr.push_back(e);                                //push进栈attr
474                 S.push(cnt++);                                    //S中push的当前的节点号
475                 c.erase(c.begin());                                //pop出栈c
476             }
477             else {
478                 action.erase(0, 1);
479                 int num = atoi(action.c_str());
480                 Production p = vp[num];                    //用第num条产生式规约
481                 int len = p.second.size();                //second的长度
482                 queue<int> son;                            //son暂时记录栈S中pop的节点
483                 while (len--) {
484                     top--;                                //pop栈a
485                     b.pop_back();                        //pop栈b
486                     son.push(S.top());                    //son先记录下S需要pop的节点
487                     S.pop();                                //pop栈S
488                 }
489                 b.push_back(make_pair(p.first, e));        //push栈b
490                 symbol.push_back(p.first);                //push栈symbol
491                 attr.push_back(e);                        //push栈attr
492                 S.push(cnt++);                            //push栈S
493                 while (!son.empty()) {
494                     G[cnt - 1].push_back(son.front());    //构造Tree
495                     son.pop();
496                 }
497                 a[top++] = atoi(lr1[a[top - 1]][Hash[p.first]].c_str());    //push栈a
498             }
499         }
500         fout << endl << endl;
501
502         fout << "语法树" << endl;    //输出语法树
503         per(i, 1, cnt) if (!G[i].empty()) {
504             fout << '(' << i << ',' << symbol[i] << ')' << "  ---->  ";
505             sort(all(G[i]));
506             rep(j, 0, G[i].size()) fout << '(' << G[i][j] << ',' << symbol[G[i][j]] << ')' << ' ';
507             fout << endl;
508         }
509         fout << endl << endl;
510     }
511
512     void main() {
513         project::main();
514         IN_LR1();
515         MORPHOLOGY();
516         JUDGE();
517     }
518 }
519
520 namespace translate {    //翻译
521     using namespace grammar;
522     ofstream fout("C:\\Users\\Flowersea\\Desktop\\Code.txt");
523
524     vector<vector<string>> table;    //符号表
525     int temp_cnt = 0;                //变量计数
526     int nextquad = 100;                //四元式标号
527
528     void mktable() {                    //新建符号表
529         table.push_back(vector<string>());
530     }
531
532     void rmtable() {                    //删除符号表
533         table.pop_back();
534     }
535
536     void enter(string name) {        //声明变量
537         table.back().push_back(name);
538     }
539
540     string lookup(string name) {        //查看变量是否存在
541         per(i, 0, table.size()) rep(j, 0, table[i].size())
542             if (table[i][j] == name) return name;
543         return "nil";
544     }
545
546     string newtemp() {                //新建一个变量
547         return "T" + to_string(++temp_cnt);
548     }
549
550     pair<int, vector<string>> gen(string a, string b, string c, string d) {    //生成四元式
551         vector<string> vs{ a,b,c,d };
552         return make_pair(nextquad++, vs);
553     }
554
555     void dfs(int u) {    //遍历语法树
556         if (G[u].empty()) return;                        //如果为空直接return
557         if (symbol[G[u].front()] == "{") mktable();        //如果第一个儿子为{,新建符号表
558         rep(i, 0, G[u].size()) dfs(G[u][i]);                //遍历所有的儿子节点
559
560         E &e = attr[u];                                    //e为attr[u]的引用,便于直接修改
561         e = attr[G[u][0]];                                //简写,把第一个儿子的直接赋值给attr[u]
562         attr[u].code.clear();                            //先清空code四元式
563         rep(i, 0, G[u].size()) {                            //把所有儿子的四元式加进来
564             for (auto it : attr[G[u][i]].code) {
565                 e.code.push_back(it);
566             }
567         }
568
569         if (symbol[u] == "variable_definition") {//函数定义
570             string name = attr[G[u][1]].name;
571             enter(name);
572         }
573         else if (symbol[u] == "assignment_expression" && symbol[G[u][0]] == "ID") {//赋值语句
574             string p = lookup(attr[G[u][0]].name);    //查符号表
575             if (p == "nil") {
576                 cerr << "变量未声明" << endl;
577                 return;
578             }
579             e.place = p;
580             e.code.push_back(gen("=", attr[G[u][2]].place, "-", e.place));
581         }
582         else if (symbol[u] == "primary_expression" && symbol[G[u][0]] == "NUM") {//规约NUM
583             e.place = newtemp();
584             e.value = attr[G[u][0]].value;
585             e.code.push_back(gen("=", e.value, "-", e.place));
586         }
587         else if (symbol[u] == "primary_expression" && symbol[G[u][0]] == "ID") {    //规约ID
588             string p = lookup(attr[G[u][0]].name);
589             if (p == "nil") {
590                 cerr << "变量未声明" << endl;
591                 return;
592             }
593             e.place = p;
594             e.name = attr[G[u][0]].name;
595         }
596         else if (symbol[u] == "multiplicative_expression" && G[u].size() > 1 && symbol[G[u][1]] == "*") {//乘法表达式
597             E e1 = attr[G[u][0]];
598             E e2 = attr[G[u][2]];
599             e.place = newtemp();
600             e.code.push_back(gen("*", e1.place, e2.place, e.place));
601         }
602         else if (symbol[u] == "additive_expression" && G[u].size() > 1 && symbol[G[u][1]] == "+") {//加法表达式
603             E e1 = attr[G[u][0]];
604             E e2 = attr[G[u][2]];
605             e.place = newtemp();
606             e.code.push_back(gen("+", e1.place, e2.place, e.place));
607         }
608         else if (symbol[u] == "relational_expression" && G[u].size() > 1) {//关系表达式
609             E id1 = attr[G[u][0]];
610             E id2 = attr[G[u][2]];
611             e.code.push_back(gen("j" + symbol[G[u][1]], id1.place, id2.place, "0"));
612             e.True = e.code.back().first;
613             e.code.back().second[3] = to_string(e.code.back().first + 2);
614             e.code.push_back(gen("j", "-", "-", "0"));
615             e.False = e.code.back().first;
616         }
617         else if (symbol[G[u][0]] == "WHILE") {//WHILE语句
618             e = attr[G[u][0]];
619             attr[u].code.clear();
620             for (auto it : attr[G[u][2]].code)
621                 e.code.push_back(it);
622             for (auto it : attr[G[u][4]].code)
623                 e.code.push_back(it);
624             e.code.push_back(gen("j", "-", "-", to_string(e.code.front().first)));
625
626             for (auto &it : e.code) {
627                 if (it.first == attr[G[u][2]].False) {
628                     it.second[3] = to_string(e.code.back().first + 1);
629                     break;
630                 }
631             }
632             e.code.back().second[3] = to_string(e.code.front().first);
633         }
634         else if (symbol[G[u][0]] == "IF" && G[u].size() == 5) {//IF语句
635             e = attr[G[u][0]];
636             attr[u].code.clear();
637             for (auto it : attr[G[u][2]].code)
638                 e.code.push_back(it);
639             for (auto it : attr[G[u][4]].code)
640                 e.code.push_back(it);
641             for (auto &it : e.code) {
642                 if (it.first == attr[G[u][2]].False) {
643                     it.second[3] = to_string(e.code.back().first + 1);
644                     break;
645                 }
646             }
647         }
648         else if (symbol[G[u][0]] == "IF" && G[u].size() == 7) {//IF ELSE语句
649             e = attr[G[u][0]];
650             attr[u].code.clear();
651             for (auto it : attr[G[u][2]].code)
652                 e.code.push_back(it);
653             for (auto it : attr[G[u][4]].code)
654                 e.code.push_back(it);
655             e.code.push_back(gen("j", "-", "-", to_string(e.code.back().first + attr[G[u][6]].code.size() + 2)));
656             e.code.back().first = e.code.front().first + e.code.size() - 1;
657             for (auto &it : e.code) {
658                 if (it.first == attr[G[u][2]].False) {
659                     it.second[3] = to_string(e.code.back().first + 1);
660                     break;
661                 }
662             }
663             for (auto it : attr[G[u][6]].code) {
664                 it.first++;
665                 if (it.second[0][0] == 'j') {
666                     int num = atoi(it.second[3].c_str());
667                     it.second[3] = to_string(num + 1);
668                 }
669                 e.code.push_back(it);
670             }
671         }
672
673         if (symbol[G[u].back()] == "}") rmtable();        //如果最后一个儿子为},删除符号表
674     }
675
676     void main() {
677         int rt = cnt - 1;    //rt为根节点
678         dfs(rt);
679         for (auto it : attr[rt].code)
680             fout << it.first << " (" << it.second[0] << ", " << it.second[1]
681             << ", " << it.second[2] << ", " << it.second[3] << ")" << endl;
682         fout << nextquad << endl;    //多输出一行
683     }
684 }
685
686 int main() {
687     //lr1::main();
688     grammar::main();
689     translate::main();
690     return 0;
691 }

源码下载:https://download.csdn.net/download/baocong1214/10511976

转载于:https://www.cnblogs.com/baocong/p/9242321.html

LR(1)分析表-语法树-四元式相关推荐

  1. C++实现的利用LR(1)分析表对赋值表达式进行语法制导翻译生成四元式及汇编代码

    赋值语句的语法制导翻译 后续已完善算术运算文法.赋值文法.布尔运算文法.if.while.do-while和复合语句文法,编译器项目已上传GitHub,https://github.com/sleep ...

  2. 【编译原理笔记06】语法分析,移入-归约分析:自底向上的分析,LR(0)分析法,LR(0)分析表的构建(基于自动机)

    本次笔记内容: 4-8 自底向上的分析概述 4-9 LR分析法概述 4-10 LR0分析 4-11 LR0分析表构造 本节课幻灯片,见于我的 GitHub 仓库:第6讲 语法分析_3.pdf 本节课介 ...

  3. [编译原理]DO-WHILE循环语句的翻译程序设计(LR(1)方法、输出四元式)C++实现

    题目: DO-WHILE循环语句的翻译程序设计(LR(1)方法.输出四元式) 1 课设任务概述 初始条件: ​ 理论:完成编译原理,数据结构.高级编程语言.汇编语言等相关课程的学习,基于计算机专业知识 ...

  4. LR(0)分析表的构建

    LR(0)分析表的构建 一.实验要求 构建LR(0)分析表 例: G[E]: E->aA E->bB A->cA A->d B->cB B->d 二.实验原理 在网 ...

  5. C++实现LR(1)分析表的构造

    构造LR(1)分析表的算法参考了龙书本科教学版: 龙书给的例子:(1)S′→S(2)S→CC(3)C→cC∣d\begin{aligned} &(1) S' \rightarrow S \\ ...

  6. LR(0)项目集规范族的构造及LR(0)分析表的构造

    求出文法的所有项目,按一定规则构造识别活前缀的NFA, 再确定化为DFA确定化的工作量较大,而且容易出错,实际应用中并不使用,这里介绍的目的仅仅是为了便于理解.具体见识别活前缀的有限自动机构建方法_用 ...

  7. 【编译原理】 LR(0) 分析表

    LR(0) 步骤 1. 写成 拓广文法 (S'→ S) 2. 活前缀的 DFA(靠近.后面的非终结符) 看状态Ii里面,是不是只存在一个规约项目.如果有两个规约项目,就是规约--规约冲突:如果同时有规 ...

  8. java pl0 四元式,【编译原理】c++实现自下而上语法分析及中间代码(四元式)生成...

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  9. 【编译原理】WHILE循环语句的翻译程序设计与实现(递归下降法、输出四元式)(赋值语句的词法分析、语义分析)

    注:本文记录 WHUT-计算机学院-编译原理 课程 课内实践 >>点击查看武汉理工大学计算机专业课程资料汇总 项目下载地址:https://download.csdn.net/downlo ...

最新文章

  1. 分布式MySQL数据库TDSQL架构分析
  2. 网桥如何把信号传给服务器,无线网桥传输的三种传输方式
  3. linux内核启动以及文件系统的加载过程
  4. 初级菜鸟程序员浅谈开源和共享精神
  5. manjaro软件源报错 不停看到错误 “PackageName: signature from “User <email@archlinux.org>“ is invalid“ 的几种解决方法
  6. Silverlight5 RC调用Win32API
  7. 拓端tecdat|R语言进行数据结构化转换:Box-Cox变换、“凸规则”变换方法
  8. jQuery 5 条件选择器
  9. photoshop 新建文档尺寸预设如何导出保存
  10. DXGI高帧率屏幕录像软件源码解析(声音捕获,抓屏,ffmpeg录像,MP4录像,flv录像,麦克风采集)(第4篇编码,录像部分)
  11. c语言char sex是什么意思,2012年计算机二级C语言入门教程:结构体
  12. js实现双人对战五子棋
  13. 企业版微信公众号从零开始之二(申请认证流程)
  14. 2022淘宝双十一优惠券如何叠加使用?淘宝双十一优惠券叠加规则介绍
  15. 苹果 2019 卖什么?新 iPhone 值不值得买?
  16. 【Linux】设备驱动简述,快速认知
  17. 支付宝wap支付开通流程
  18. 收藏,全网开发者都在学的26门AI课程!
  19. 景联文科技出席全国信标委生物特征识别委会2021年下半年工作组集中会议
  20. SpringBoot入门学习(六)之云收藏项目

热门文章

  1. 用jquery mobile 实现幻灯片效果
  2. java.net.inetaddress_java.net.InetAddress类的应用
  3. Java String关于replaceall函数转义字符的一个小贴士
  4. Java开发-Redis客户端Jedis
  5. Leetcode 98. 验证二叉搜索树 解题思路及C++实现
  6. Numpy数组常用函数汇总(数学运算、三角函数、位运算、比较运算及其它)
  7. 高数第七版_习题解答_3-1行列式习题
  8. 基于注解的 IOC 配置——创建对象(Component、Controller、Service、Repository)注入数据(Autowired、Qualifier、Resource、Value)
  9. MyBatis-Plus 通用IService的使用
  10. 用javascript实现简单的物质(密度)分布图