軟件構造——LL(1)語法分析


實驗目的

 

通過完成預測分析法的語法分析程序,了解預測分析法和遞歸子程序法的區別和聯系。使了解語法分析的功能,掌握語法分析程序設計的原理和構造方法,訓練掌握開發應用程序的基本方法。

 

實驗內容

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 << "\n歡迎使用周博 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 << "\n以下是預測分析表" << 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 << "\n句子" << 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 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM