LR(1)分析表-语法树-四元式

 这学期的编译原理终于学完了,不愧是号称最难的科目。要用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

posted @ 2018-06-29 10:55  Flowersea  阅读(7056)  评论(3编辑  收藏  举报