编译原理 算法3.8 LR分析 c++11实现

LR分析简介

  LR分析是应用最广泛的一类分析方法,它是实用的编译器功能中最强的分析器,其特点是:

  1,采用最一般的无回溯移进-规约方法。

  2,可分析的文法是LL文法的真超集。

  3,能够及时发现错误,及时从左扫描输入序列的最大可能。

  4,分析表较为复杂,难以手工构造。

实验内容

  根据LR分析表action和goto实现LR分析。

实验步骤

  输入 序列$\omega$和文法$G$的LR分析表action与goto。

  输出 若$\omega \in L(G)$,得到$\omega$的规范规约,否则指出一个错误。

具体实现

  见代码。

  1 #include <algorithm>
  2 #include <fstream>
  3 #include <iostream>
  4 #include <map>
  5 #include <set>
  6 #include <stack>
  7 #include <vector>
  8 using namespace std;
  9 
 10 using Production = pair<string, vector<string>>;
 11 
 12 const int max_state = 110;
 13 const int delay_num = 5e8;
 14 
 15 struct ParserLR
 16 {
 17 
 18     map<string, int> mp_n; //非终结符映射
 19     map<string, int> mp_t; //终结符映射
 20     vector<Production> P;  //产生式
 21     vector<string> N, T;   //非终结符,终结符
 22     int state_num, operator_num, nonterminal_num, terminal_num, production_num;
 23     vector<string> action[max_state];
 24     vector<int> _goto[max_state];
 25     int init(string filename)
 26     {
 27         N.clear();
 28         T.clear();
 29         P.clear();
 30         mp_n.clear();
 31         mp_t.clear();
 32         for (int i = 0; i < max_state; i++)
 33         {
 34             action[i].clear();
 35             _goto[i].clear();
 36         }
 37         state_num = operator_num = nonterminal_num = terminal_num = production_num = 0;
 38         ifstream in(filename, ios::in);
 39         if (!in.is_open())
 40             return 0;
 41         in >> terminal_num;
 42         for (int i = 0; i < terminal_num; i++)
 43         {
 44             string tmp;
 45             in >> tmp;
 46             T.emplace_back(tmp);
 47             mp_t[tmp] = i;
 48         }
 49         in >> nonterminal_num;
 50         for (int i = 0; i < nonterminal_num; i++)
 51         {
 52             string tmp;
 53             in >> tmp;
 54             N.emplace_back(tmp);
 55             mp_n[tmp] = i;
 56         }
 57         in >> production_num;
 58         for (int i = 0; i < production_num; i++)
 59         {
 60             Production cur;
 61             in >> cur.first;
 62             int sz;
 63             in >> sz;
 64             for (int j = 0; j < sz; j++)
 65             {
 66                 string t;
 67                 in >> t;
 68                 cur.second.emplace_back(t);
 69             }
 70             P.emplace_back(cur);
 71         }
 72         in >> state_num;
 73         for (int i = 0; i <= state_num; i++)
 74             for (int j = 0; j < terminal_num; j++)
 75             {
 76                 string tmp;
 77                 in >> tmp;
 78                 action[i].emplace_back(tmp);
 79             }
 80         for (int i = 0; i <= state_num; i++)
 81             for (int j = 0; j < nonterminal_num; j++)
 82             {
 83                 int tmp;
 84                 in >> tmp;
 85                 _goto[i].emplace_back(tmp);
 86             }
 87         return 1;
 88     }
 89     Production getProduction(int idx)
 90     {
 91         return P[idx - 1];
 92     }
 93     pair<int, vector<Production>> analyze(vector<string> input) //first->出错位置,-1代表无错
 94     {
 95         vector<Production> error;
 96         vector<Production> success;
 97         stack<string> ch; //符号栈
 98         stack<int> st;    //状态栈
 99         ch.emplace("#");
100         st.emplace(0);
101         input.emplace_back("#");
102         int sz = input.size();
103         for (int i = 0; i < sz;)
104         {
105             string now = input[i];
106             if (!mp_t.count(now))
107                 return make_pair(i, success);
108             int ip = mp_t[now];
109             int top = st.top(); //栈顶状态
110             string at = action[top][ip];
111             if (at[0] == 'r') //规约
112             {
113                 string res = at.substr(1, at.size());
114                 int num = stoi(res);
115                 Production trans = getProduction(num);
116                 for (int i = 0; i < trans.second.size(); i++)
117                 {
118                     st.pop();
119                     ch.pop();
120                 }
121                 top = st.top();
122                 string cur = trans.first;
123                 ch.emplace(cur);
124                 st.emplace(_goto[top][mp_n[cur]]);
125                 success.emplace_back(trans);
126             }
127             else if (at[0] == 's') //移进
128             {
129                 string res = at.substr(1, at.size());
130                 int to_state = stoi(res);
131                 st.emplace(to_state);
132                 ch.emplace(now);
133                 i++;
134             }
135             else if (at == "acc") //接受
136                 return make_pair(-1, success);
137             else //error
138             {
139                 if (now == "#")
140                     return make_pair(i - 1, success);
141                 return make_pair(i, success);
142             }
143         }
144         return make_pair(1, error);
145     }
146 };
147 inline void delay()
148 {
149     for (int i = 0; i < delay_num; i++)
150         ;
151 }
152 inline void display(const pair<int, vector<Production>> &out)
153 {
154     if (out.first == -1)
155     {
156         for (int i = 0; i < out.second.size(); i++)
157         {
158             cout << out.second[i].first << "->";
159             for (int j = 0; j < out.second[i].second.size(); j++)
160                 cout << out.second[i].second[j];
161             cout << "\n";
162         }
163     }
164     else
165         cout << "在第" << out.first + 1 << "个终结符出错.\n";
166 }
167 int main(int argc, char const *argv[])
168 {
169     ParserLR app;
170     string filename = "prj3_8_in.txt";
171     if (app.init(filename))
172     {
173 
174         cout << "构建分析器中";
175         delay();
176         cout << ".";
177         delay();
178         cout << ".";
179         delay();
180         cout << ".\n";
181         delay();
182         cout << "构建成功.\n";
183         cout << "请输入终结符个数:";
184         int sz;
185         cin >> sz;
186         cout << "请输入包含" << sz << "个终结符的待分析序列, 终结符间需用空格分离:";
187         vector<string> al;
188         for (int i = 0; i < sz; i++)
189         {
190             string tmp;
191             cin >> tmp;
192             al.emplace_back(tmp);
193         }
194         cout << "开始分析";
195         delay();
196         cout << ".";
197         delay();
198         cout << ".";
199         delay();
200         cout << ".\n";
201         delay();
202         cout << "分析结束.\n";
203         pair<int, vector<Production>> out = app.analyze(al);
204         cout << "分析成功,结果如下:\n";
205         display(out);
206     }
207     return 0;
208 }
源代码
4 
id - * #
3
E T F
6
E 3 E - T
E 1 T
T 3 T * F
T 1 F
F 2 - F
F 1 id
10
s4 s5 null null
null s6 null acc
null r2 s7 r2
null r4 r4 r4
null r6 r6 r6
s4 s5 null null
s4 s5 null null
s4 s5 null null
null r5 r5 r5
null r1 s7 r1
null r3 r3 r3
1 2 3
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 8
-1 9 3
-1 -1 10
-1 -1 -1
-1 -1 -1
-1 -1 -1
输入文件

 

效果展示

 

 

 

代码使用部分c++11特性,如有本地编译需要,请确认环境。

欢迎下方留言。

 

posted @ 2019-12-10 21:59  mool  阅读(1036)  评论(0编辑  收藏  举报