编译原理实验(二)
實驗二 LL(1) 分析法
一、實驗目的
根據某一文法編制調試LL(1)分析程序,以便對任意輸入的符號串進行分析。本次實驗的目的主要是加深對預測分析LL(1)分析法的理解。
二、實驗題目
實驗規定對下列文法,用LL(1)分析法對任意輸入的符號串進行分析:
若輸入串為 i+i?i#i+i*i\#i+i?i# ,則輸出為:
LL(1) 的分析表為
| E | e | e | Select(E→TG)={(,i}Select(E→TG)=\{(,i\}Select(E→TG)={(,i} | ||||
| G | g | g1 | g1 | $ Select (G→+TG)={+} \Select (G→\epsilon)={#,)}$ | |||
| T | t | t | $ Select (T→FS)={(,i} $ | ||||
| S | s1 | s | s1 | s1 | Select(S→?FS)={?}Select(S→?)={#,)+}Select (S→*FS)=\{*\} \\Select (S→?)=\{\#,) +\}Select(S→?FS)={?}Select(S→?)={#,)+} | ||
| F | f1 | f | $ Select (F→(E))={(} \Select (F→i)={i}$ |
三、編碼實現
源代碼
#include <iostream> #include<cstdio> #include<cstring> #include <stack> #include <string> #include "structure.h" #include "iomanip"std::stack<char> A; // analysis stack std::string B; // left stringstd::string keyWords = "i+*()#"; // terminals std::string aggregate = "EGTSF"; // nonterminal aggregateint j = 0, b = 0, m, n; char ch, x;/*x為當前棧頂字符*/ int flag = 0; char temp;int count = 0;void print() {std::stack<char> A1;std::string s;A1 = A;while (!A1.empty()) {s = A1.top() + s;A1.pop();}s = s + temp;std::cout << std::left << std::setw(10) << count;std::cout << std::left << std::setw(10) << s;s.clear(); }void print1() {for (int i = 0; i < b; i++) {// printf(" ");break;}// std::cout << std::left << std::setw(10) << count;std::cout << std::left << std::setw(10) << B.substr(b, B.length()); }int main() {type e, t, g, g1, s, s1, f, f1, cha;/*結構體變量 */type C[10][10];e.origin = 'E';strcpy(e.array, "TG");e.length = 2;/*更改 length 賦值*/t.origin = 'T';strcpy(t.array, "FS");t.length = 2;/*更改 length 賦值*/g.origin = 'G';strcpy(g.array, "+TG");g.length = 3;/*更改 length 賦值*/g1.origin = 'G';g1.array[0] = '^';g1.array[1] = '\0';/*更改 字符串結束標志*/g1.length = 1;/*更改 length 賦值*/s.origin = 'S';strcpy(s.array, "*FS");s.length = 3;/*更改 length 賦值*/s1.origin = 'S';s1.array[0] = '^';s1.array[1] = '\0';/*更改 字符串結束標志*/s1.length = 1;/*更改 length 賦值*/f.origin = 'F';strcpy(f.array, "(E)");f.length = 3;/*更改 length 賦值*/f1.origin = 'F';f1.array[0] = 'i';f1.array[1] = '\0';/*更改 字符串結束標志*/f1.length = 1;/*更改 length 賦值*//** init analysis from*/for (m = 0; m <= 4; m++) {/*初始化分析表*/for (n = 0; n <= 5; n++) {C[m][n].origin = 'N';/*全部賦為空*/}}/** filing the from*/C[0][0] = e;C[0][3] = e;C[1][1] = g;C[1][4] = g1;C[1][5] = g1;C[2][0] = t;C[2][3] = t;C[3][1] = s1;C[3][2] = s;C[3][4] = C[3][5] = s1;C[4][0] = f1;C[4][3] = f;/** get string*/std::string T;std::getline(std::cin, T);for (auto i : T) {if (i == ' ') {continue;} else if ((i != 'i') && (i != '+') && (i != '*') && (i != '(') && (i != ')') && (i != '#')) {std::cout << "Error!Illegal character: " << ch << std::endl;非法字符的處理
exit(1);} else {B.push_back(i);}}ch = B[0];// analysis string AA.push('#');A.push('E');std::cout << std::left << std::setw(10) << "step";std::cout << std::left << std::setw(10) << "stack";std::cout << std::left << std::setw(10) << "left";std::cout << std::left << std::setw(10) << "p.r" << std::endl;do {// analysisx = A.top();// std::cout << x << std::endl;temp = x;A.pop();// std::cout << k++;// std::cout << " ";for (j = 0; j <= 5; j++) { // is terminal characterif (x == keyWords[j]) {flag = 1;break;}}if (flag == 1) {if (x == '#') {if (ch == '#') {count++;print();print1();/** the stack have already cleared*/std::cout << "accept";getchar();getchar();exit(1);} else {count++;print();print1();std::cout << "error:";std::cout<< "Illegal situation:'#' have already in analysis stack, but there are characters left in left string!";getchar();getchar();exit(1);}} else if (cha.origin == 'N' && ch == '#'){count++;print();print1();std::cout << "error:";std::cout<< "Illegal situation:'#' have already in analysis stack, but there are characters left in left string!";getchar();getchar();exit(1);}else if (x == ch) {count++;print();print1();std::cout << std::left << ch << "match" << std::endl;// std::cout << b;b++;ch = B[b];flag = 0;} else {if (ch == '#') {count++;print();print1();std::cout << "Error!" << std::endl;std::cout<< "illegal situation:'#' have already in left vector, but there are characters left in analysis stack!"<< std::endl;getchar();getchar();exit(0);} else {count++;print();print1();std::cout << ch << "match error" << std::endl;// printf("%c match error!\n", ch);/*輸出出錯終結符*/getchar();getchar();exit(1);}}} else { // nonterminal characterfor (j = 0; j <= 4; j++)if (x == aggregate[j]) {m = j;/*行號*/break;}for (j = 0; j <= 5; j++)if (ch == keyWords[j]) {n = j; /*列號*/break;}cha = C[m][n];if (cha.origin != 'N') {count++;print();print1();std::cout << std::left << cha.origin << "->";// printf("%c->", cha.origin);for (j = 0; j < cha.length; j++) {std::cout << cha.array[j];}std::cout << '\n';for (j = (cha.length - 1); j >= 0; j--) {A.push(cha.array[j]);if (A.top() == '^') {A.pop();}}} else if (cha.origin == 'N' && ch == '#'){count++;print();print1();std::cout << "error:";std::cout<< "Illegal situation:'#' have already in analysis stack, but there are characters left in left string!";getchar();getchar();exit(1);}else {count++;print();print1();std::cout << "Error!Not found!" << std::endl;getchar();getchar();exit(0);}}} while (true); }改進與提升
增加了三種錯誤處理:非法符號、未找到對應產生式、多余符號。
四、運行與結果展示
-
(i?i)+i#(i * i) + i \#(i?i)+i#
符合該文法,語句被接受
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Z0sLpjgn-1636039046674)(C:\Users\Lunatic\Desktop\編譯原理實驗\實驗二\1.jpg)]
-
i+l#i + l \#i+l#
非法符號
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-E5fIB42t-1636039046683)(C:\Users\Lunatic\Desktop\編譯原理實驗\實驗二\2.jpg)]
-
i+ii#i + ii \#i+ii#
無對應產生式
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VTnLmFnj-1636039046687)(C:\Users\Lunatic\Desktop\編譯原理實驗\實驗二\3.jpg)]
-
i)#i)\#i)#
多余符號
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oRq6Kz9h-1636039046689)(C:\Users\Lunatic\Desktop\編譯原理實驗\實驗二\4.jpg)]
總結
- 上一篇: gta5维护服务器,GTA6再等10年?
- 下一篇: 解决win10搜索框无法搜索本地应用或无