软件构造——LL语法分析

Posted smartisn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件构造——LL语法分析相关的知识,希望对你有一定的参考价值。

实验目的

 

通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。

 

实验内容

u  根据某一文法编制调试 LL ( 1 )分析程序,以便对任意输入的符号串进行分析。

u  构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。

u  分析法的功能是利用LL(1)控制程序根据显示栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

设计思想

(1)定义部分:定义常量、变量、数据结构。

(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);

(3)控制部分:从键盘输入一个表达式符号串;

(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

 

【实验要求】

(1)编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

(2)如果遇到错误的表达式,应输出错误提示信息。

(3)画出流程图

技术图片

 

实验截图:

 技术图片

 

 技术图片

 

 

代码:

  1 Base.sh
  2 #ifndef _BASE_H_
  3 #define _BASE_H_
  4 #include <iostream>
  5 #include <iomanip>
  6 #include <string>
  7 #include <vector>
  8 #include <set>
  9 
 10 #define maxsize 100
 11 
 12 using namespace std;
 13 
 14 struct node {  // 产生式的数据结构
 15     char left;
 16     string right;
 17 };
 18 
 19 class Base {
 20 protected:
 21     int T;
 22     node production[maxsize]; // 产生式集
 23 
 24     set<char> firstSet[maxsize];  // First集
 25     set<char> followSet[maxsize];  // Follow集
 26     vector<char> terminalNoEmpty; // 去$(空)的终结符
 27     vector<char> terminal;  // 终结符
 28     vector<char> nonterminal;  // 非终结符
 29 
 30     bool isNonterminal(char c);
 31     int getIndex(char target);  // 获得target在终结符集合中的下标
 32     int getNIndex(char target);  // 获得target在非终结符集合中的下标
 33     void getFirst(char target);  // 得到First(target)
 34     void getFollow(char target);  // 得到Follow(target)
 35 
 36 public:
 37     Base() {};
 38 
 39     void inputAndSolve();  // 处理和求出First和Follow集
 40     void displayFirstAndFollow();  // 输出First和Follow集
 41 
 42 };
 43 #endif 
 44 
 45 Base.cpp
 46 #include "Base.h"
 47 
 48 bool Base::isNonterminal(char c) { // 判断c是否为非终结符
 49     if (c >= A && c <= Z)
 50         return true;
 51     return false;
 52 }
 53 int Base::getNIndex(char target) {  // 获得target在非终结符集合中的下标
 54     for (int i = 0; i<nonterminal.size(); i++) {
 55         if (target == nonterminal[i])
 56             return i;
 57     }
 58     return -1;
 59 }
 60 int Base::getIndex(char target) {  // 获得target在终结符集合中的下标
 61     for (int i = 0; i<terminalNoEmpty.size(); i++) {
 62         if (target == terminalNoEmpty[i])
 63             return i;
 64     }
 65     return -1;
 66 }
 67 
 68 void Base::getFirst(char target) {  // 求FIRST(target)
 69     int countEmpty = 0;  // 用于最后判断是否有空
 70     int isEmpty = 0;
 71     int targetIndex = getNIndex(target);
 72     for (int i = 0; i < T; i++) {
 73         if (production[i].left == target) {  // 匹配产生式左部
 74             if (!isNonterminal(production[i].right[0])) {  // 对于终结符,直接加入first
 75                 firstSet[targetIndex].insert(production[i].right[0]);
 76             }
 77             else {
 78                 for (int j = 0; j < production[i].right.length(); j++) { // X->Y1..Yj..Yk是一个产生式
 79                     char Yj = production[i].right[j];
 80                     if (!isNonterminal(Yj)) {  // Yj是终结符(不能产生空),FIRST(Yj)=Yj加入FIRST(X),不能继续迭代,结束
 81                         firstSet[targetIndex].insert(Yj);
 82                         break;
 83                     }
 84                     getFirst(Yj);// Yj是非终结符,递归 先求出FIRST(Yj)
 85 
 86                     set<char>::iterator it;
 87                     int YjIndex = getNIndex(Yj);
 88                     for (it = firstSet[YjIndex].begin(); it != firstSet[YjIndex].end(); it++) {
 89                         if (*it == $)  // 遍历查看FIRST(Yj)中是否含有‘$‘(能产生空)
 90                             isEmpty = 1;
 91                         else
 92                             firstSet[targetIndex].insert(*it);//将FIRST(Yj)中的非$就加入FIRST(X)
 93                     }
 94                     if (isEmpty == 0)  // Yj不能产生空, 迭代结束
 95                         break;
 96                     else {   //  Yj能产生空
 97                         countEmpty += isEmpty;
 98                         isEmpty = 0;
 99                     }
100                 }
101                 if (countEmpty == production[i].right.length())//所有右部first(Y)都有$(空),将$加入FIRST(X)中
102                     firstSet[getNIndex(target)].insert($);
103             }
104         }
105     }
106 }
107 
108 void Base::getFollow(char target) {  // 求FOLLOW(target)
109     int targetIndex = getNIndex(target);
110     for (int i = 0; i<T; i++) {
111         int index = -1;
112         int len = production[i].right.length();
113         for (int j = 0; j < len; j++) {  // 寻找target在产生式中的位置index
114             if (production[i].right[j] == target) {
115                 index = j;
116                 break;
117             }
118         }
119         if (index != -1 && index < len - 1) {  // 找到target在产生式中的位置index
120             // 存在A->αBβ, 将FIRST(β)中除了空$之外的所有放入FOLLOW(B)中
121             // 这里B对应target, β对应nxt
122             char nxt = production[i].right[index + 1];
123             if (!isNonterminal(nxt)) {  // β是终结符 FIRST(β)=β,直接插入β
124                 followSet[targetIndex].insert(nxt);
125             }
126             else {  // β是非终结符
127                 int hasEmpty = 0;
128                 set<char>::iterator it;
129                 int nxtIndex = getNIndex(nxt);  // 插入FIRST(β)中除了空$之外的所有
130                 for (it = firstSet[nxtIndex].begin(); it != firstSet[nxtIndex].end(); it++) {
131                     if (*it == $)
132                         hasEmpty = 1;
133                     else
134                         followSet[targetIndex].insert(*it);
135                 }
136 
137                 if (hasEmpty && production[i].left != target) { // 存在A->αBβ且FIRST(β)->$
138                     // FOLLOW(A)放在FOLLOW(B)中
139                     getFollow(production[i].left);
140                     set<char>::iterator it;
141                     char tmp = production[i].left;
142                     int tmpIndex = getNIndex(tmp);
143                     for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
144                         followSet[targetIndex].insert(*it);
145                 }
146             }
147         }
148         else if (index != -1 && index == len - 1 && target != production[i].left) {  // 存在A->αB ,FOLLOW(A)放在FOLLOW(B)中
149             getFollow(production[i].left);
150             set<char>::iterator it;
151             char tmp = production[i].left;
152             int tmpIndex = getNIndex(tmp);
153             for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
154                 followSet[targetIndex].insert(*it);
155         }
156     }
157 }
158 
159 void Base::inputAndSolve() {  // 处理和求出First和Follow集
160     string s;
161     cout << "输入的产生式的个数:" << endl;
162     cin >> T;
163     cout << "输入的产生式:" << endl;
164     for (int index = 0; index < T; index++) {  // 处理每一个产生式
165         cin >> s;
166         string temp = "";  // 存储去掉空格的产生式
167         for (int i = 0; i < s.length(); i++) {  // 去掉产生式中的‘ ‘
168             if (s[i] !=  )
169                 temp += s[i];
170         }
171         production[index].left = temp[0];  // 产生式的左部
172         for (int i = 3; i<temp.length(); i++) // 产生式的右部
173             production[index].right += temp[i];
174 
175         for (int i = 0; i < temp.length(); i++) {  // 存储所有终结符和非终结符
176             if (i == 1 || i == 2) continue;  // 跳过产生符号->
177             if (isNonterminal(temp[i])) {  //插入一个非终结符
178                 int flag = 0;
179                 for (int j = 0; j < nonterminal.size(); j++) {
180                     if (nonterminal[j] == temp[i]) {
181                         flag = 1;
182                         break;
183                     }
184                 }
185                 if (!flag) nonterminal.push_back(temp[i]);
186             }
187             else {                       //插入一个终结符
188                 int flag = 0;
189                 for (int j = 0; j < terminal.size(); j++) {
190                     if (terminal[j] == temp[i]) {
191                         flag = 1;
192                         break;
193                     }
194                 }
195                 if (!flag) terminal.push_back(temp[i]);
196             }
197         }
198     }
199     terminal.push_back(#);
200 
201     for (int i = 0; i < terminal.size(); i++) { // 存储没有$符号的终结符
202         if (terminal[i] != $)
203             terminalNoEmpty.push_back(terminal[i]);
204     }
205 
206     // 获得first集
207     for (int i = 0; i < nonterminal.size(); i++) {
208         getFirst(nonterminal[i]);
209     }
210 
211     // 获得follow集
212     for (int i = 0; i < nonterminal.size(); i++) {
213         if (i == 0)  // 开始符号, 先加入结束符号
214             followSet[0].insert(#);
215         getFollow(nonterminal[i]);
216     }
217 }
218 
219 void Base::displayFirstAndFollow() {  // 输出First和Follow集
220     for (int aa = 0; aa < 10; aa++)
221     {
222         cout << "*********";
223     }
224     cout << "
欢迎使用周博 20173599 LL1语法分析器(以下是First集合和Follow集合)" << endl;
225     cout << "FIRST集合" << endl;
226     for (int i = 0; i<nonterminal.size(); i++) {
227         cout << nonterminal[i] << ": ";
228         set<char>::iterator it;
229         for (it = firstSet[i].begin(); it != firstSet[i].end(); it++)
230             cout << *it << "  ";
231         cout << endl;
232     }
233     cout << endl;
234 
235     cout << "FOLLOW集合" << endl;
236     for (int i = 0; i<nonterminal.size(); i++) {
237         cout << nonterminal[i] << ": ";
238         set<char>::iterator it;
239         for (it = followSet[i].begin(); it != followSet[i].end(); it++)
240             cout << *it << "  ";
241         cout << endl;
242     }
243     cout << endl;
244 }
245 LL1.h
246 
247 #include"Base.h"
248 
249 #define maxsize 100
250 #ifndef _LL1_H_
251 #define _LL1_H_
252 using namespace std;
253 
254 class LL1 : public Base {
255 private:
256     vector<char> analyStack; // 分析栈
257     vector<char> leftExpr;  // 剩余输入串
258     int tableMap[100][100];  // 预测表
259 
260 public:
261     LL1();
262 
263     void getTable(); // 生成预测表
264     void analyExpression(string s);  // 分析输入语句s
265     void printPredictTable();  // 输出预测表
266     void getResult(); // 综合处理
267 };
268 #endif
269 LL1.cpp
270 #include"LL1.h"
271 
272 LL1::LL1() {
273     memset(tableMap, -1, sizeof(tableMap));
274 }
275 
276 void LL1::getTable() {
277     for (int index = 0; index < T; index++) {                          // 对于每个产生式(编号index):A->α
278         int row = getNIndex(production[index].left);
279         int emptyCount = 0;
280         for (int i = 0; i < production[index].right.size(); i++) { // 1) 对FIRST(α)中的每个终结符号a,将index加入(A, a)中
281             char tmp = production[index].right[i];
282             if (!isNonterminal(tmp)) { // tmp是终结符          
283                 if (tmp != $)
284                     tableMap[row][getIndex(tmp)] = index;
285                 if (tmp == $) {
286                     emptyCount++;
287                 }
288                 break;
289             }
290             else {  // tmp是非终结符
291                 set<char>::iterator it;
292                 int tmpIndex = getNIndex(tmp);
293                 // 对FIRST(tmp)中的每个终结符号a,将i加入(A, a)中
294                 for (it = firstSet[tmpIndex].begin(); it != firstSet[tmpIndex].end(); it++) {
295                     tableMap[row][getIndex(*it)] = index;
296                 }
297                 if (firstSet[tmpIndex].count($) != 0) {      // 2) 如果空$在FIRST(tmp)中,继续看α中的下一个符号
298                     emptyCount++;
299                 }
300                 else {
301                     break;
302                 }
303             }
304         }
305 
306         // 2) 如果空$在FIRST(α)中,对FOLLOW(A)中的每个终结符或结束符b,将i加入(A,b)中
307         if (emptyCount == production[index].right.size()) {
308             set<char>::iterator  it;
309             for (it = followSet[row].begin(); it != followSet[row].end(); it++) {
310                 tableMap[row][getIndex(*it)] = index;
311             }
312         }
313     }
314 }
315 
316 void LL1::analyExpression(string s) {
317 
318     for (int i = 0; i < s.size(); i++)
319         leftExpr.push_back(s[i]);
320     leftExpr.push_back(#);
321 
322     analyStack.push_back(#);
323     analyStack.push_back(nonterminal[0]);  // 加入开始符号
324 
325     while (analyStack.size() > 0) {
326         //cout<<"分析栈:";
327         string outs = "";
328         for (int i = 0; i < analyStack.size(); i++)
329             outs += analyStack[i];
330         cout << setw(15) << outs;
331 
332         //cout<<"剩余输入串:";
333         outs = "";
334         for (int i = 0; i < leftExpr.size(); i++)
335             outs += leftExpr[i];
336         cout << setw(15) << outs;
337 
338         // 匹配
339         char char1 = analyStack.back();
340         char char2 = leftExpr.front();
341         if (char1 == char2 && char1 == #) {
342             cout << setw(15) << "Accepted!" << endl;
343             return;
344         }
345         if (char1 == char2) {
346             analyStack.pop_back();
347             leftExpr.erase(leftExpr.begin());
348             cout << setw(15) << "匹配:" << char1 << endl;
349         }
350         else if (tableMap[getNIndex(char1)][getIndex(char2)] != -1) {  // 预测表中有推倒项,可进行推导
351             int tg = tableMap[getNIndex(char1)][getIndex(char2)];
352             analyStack.pop_back();
353 
354             if (production[tg].right != "$") {
355                 for (int i = production[tg].right.length() - 1; i >= 0; i--) // 注意这里是反向的
356                     analyStack.push_back(production[tg].right[i]);
357             }
358 
359             cout << setw(15) << "推导:" << production[tg].left << "->" << production[tg].right << endl;
360         }
361         else {  // 错误
362             cout << setw(15) << "error!" << endl;
363             return;
364         }
365     }
366 }
367 
368 void LL1::printPredictTable() {
369     // 表头
370     for (int aa = 0; aa < 10; aa++)
371     {
372         cout << "*********";
373     }
374     cout << "
以下是预测分析表" << endl;
375     for (int i = 0; i < terminalNoEmpty.size(); i++) {
376         cout << setw(10) << terminalNoEmpty[i];
377     }
378     cout << endl;
379     for (int i = 0; i < nonterminal.size(); i++) {
380         cout << nonterminal[i] << ": ";
381         for (int j = 0; j < terminalNoEmpty.size(); j++) {
382             if (tableMap[i][j] == -1)
383                 cout << setw(10) << "   ";
384             else
385                 cout << setw(10) << production[tableMap[i][j]].right;
386         }
387         cout << endl;
388     }
389     cout << endl;
390 }
391 
392 void LL1::getResult() {
393     inputAndSolve();
394     displayFirstAndFollow();
395     getTable();
396     printPredictTable();
397     //栈匹配
398     string ss;
399     cout << "请输入符号串:" << endl;
400     cin >> ss;
401     for (int aa = 0; aa < 10; aa++)
402     {
403         cout << "*********";
404     }
405     cout << "
句子" << ss << "分析过程" << endl;
406     cout << setw(15) << "分析栈" << setw(15) << "剩余输入串" << setw(15) << "推导式" << endl;
407     analyExpression(ss);
408 
409 }
410 
411 
412 Main.cpp
413 #include "LL1.h"
414 #include<stdlib.h>
415 
416 int main() {
417     // $表示空, #表示终止
418     LL1 res;
419     res.getResult();
420     system("pause");
421     return 0;
422 }

以上是关于软件构造——LL语法分析的主要内容,如果未能解决你的问题,请参考以下文章

编译原理:LL文法 语法分析器(预测分析表法)

编译原理 LL语法分析器的设计与实现

编译原理 LL语法分析器的设计与实现

编译原理 LL语法分析器的设计与实现

编译原理 LL语法分析器的设计与实现

编译原理-第四章 语法分析-4.6 简单LR技术