zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    $().each和$("input[name='XXX']")
    常规JS操作
    日期大小比较JS方法
    集合迭代
    技术点1
    GItHub pages 的使用方法
    node.js是做什么的?
    jQuery基础:下(事件及动画效果)
    jQuery基础:上(样式及DOM操作)
    页码demo制作
  • 原文地址:https://www.cnblogs.com/baocong/p/9242321.html
Copyright © 2011-2022 走看看