LR(1)分析法的總控的實現(C++實現)
阿新 • • 發佈:2018-11-16
-
LR(1)分析法實驗設計思想及演算法
(1)若ACTION[sm , ai] = s則將s移進狀態棧,並把輸入符號加入符號棧,則三元式變成
為:(s0s1…sm s , #X1X2…Xm ai , ai+1…an#)
(2) 若ACTION[sm , ai] = rj則將第j個產生式A->β進行歸約。此時三元式變為
(s0s1…sm-r s , #X1X2…Xm-rA , aiai+1…an#)
(3) 若ACTION[sm , ai]為“接收”,則三元式不再變化,變化過程終止,宣佈分析成功。
(4) 若ACTION[sm , ai]為“報錯”,則三元式的變化過程終止,報告錯誤。
-
測試所用文法及其分析表
(1) E-> E+T
(2) E->T
(3) T-> T*F
(4) T->F
(5) F-> (E)
(6) F-> i
-
程式碼實現
#ifndef _LR_ #define _LR_ using namespace std; class Grammar{ public: //產生式的個數 int grammarNum ; //定義產生式陣列 string formula[100] = {" ","E->E+T","E->T","T->T*F","T->F","F->(E)","F->i"}; Grammar(){ grammarNum = 6; } }; //定義LR文法的分析表 class LRAnalyseTable{ public: char terminalChar[100]={'i','+','*','(',')','#'}; //定義終結符的個數 int terNum =6; char nonTerminalChar[100]={'E','T','F'}; //定義非終結符的個數 int nonTerNum = 3; //定義狀態數 int statusNum = 12; string action[12][6]={{"s5","","","s4","",""},{"","s6","","","","acc"},{"","r2","s7","","r2","r2"},{"","r4","r4","","r4","r4"},{"s5","","","s4","",""},{"","r6","r6","","r6","r6"},{"s5","","","s4","",""} ,{"s5","","","s4","",""},{"","s6","","","s11",""},{"","r1","s7","","r1","r1"},{"","r3","r3","","r3","r3"},{"","r5","r5","","r5","r5"}}; int goTo[12][3] = {{1,2,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{8,2,3},{-1,-1,-1},{-1,9,3},{-1,-1,10},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1}}; //獲取終結符的索引 int getTerminalIndex(char var){ for(int i=0;i<terNum;i++){ if(terminalChar[i] == var){ return i; } } return -1; } //獲取非終結符的索引 int getNonTerminalIndex(char var){ for(int i=0;i<nonTerNum;i++){ if(nonTerminalChar[i] == var){ return i; } } return -1; } }; #endif // _LR_
#include <iostream> #include <vector> #include <iomanip> #include <cstring> #include <sstream> #include "LR.h" using namespace std; //定義狀態棧 vector<int> status; //定義符號棧 vector<char> sign; //定義輸入的字串 vector<char> inputStr; //定義文法 Grammar grammar; //定義LR分析表 LRAnalyseTable analyseTable; //讀取輸入的字串 void readStr(); //對棧容器進行輸出,i=0,返回status中的字串,i=1,返回sign中的字串,i=2返回inputStr string vectTrancStr(int i); //總控,對輸入的字串進行分析 void LRAnalyse(); int main() { readStr(); LRAnalyse(); return 0; } //讀取輸入的字串 void readStr(){ char ch; cout<<"請輸入分析的字串:"; cin>>ch; while( ch != '#'){ inputStr.push_back(ch); cin>>ch; } //把#加入容器 inputStr.push_back('#'); } //對棧容器進行輸出,i=0,返回status中的字串,i=1,返回sign中的字串,i=2返回inputStr中的字串 string vectTrancStr(int i){ char buf[100]; int count = 0; //輸出狀態棧 if(i == 0){ vector<int>::iterator it =status.begin(); //將數字轉化為字串 string str,tempStr; for(it;it!= status.end();it++){ stringstream ss; ss << *it; ss >> tempStr; str+=tempStr; } return str; } //輸出符號棧 else if(i == 1){ vector<char>::iterator it = sign.begin(); for(it ; it != sign.end() ;it++){ buf[count] = *it; count++; } } //輸出待分析的字串 else{ vector<char>::iterator it = inputStr.begin(); for(it ; it != inputStr.end();it++){ buf[count] = *it; count++; } } buf[count] = '\0'; string str(buf); return str; } //總控,對輸入的字串進行分析 void LRAnalyse(){ //步驟 int step = 1; //把狀態0入棧 status.push_back(0); //把#加入符號棧 sign.push_back('#'); //輸出初始棧狀態 cout<<setw(10)<<"步驟"<<setw(10)<<"狀態棧"<<setw(10)<<"符號棧"<<setw(10)<<"輸入串"<<setw(25)<<"動作說明"<<endl; //初始狀態 int s =0; //儲存之前的狀態 int oldStatus; //獲取初始符號 char ch = inputStr.front(); //如果action[s][ch] =="acc" ,則分析成功 while(analyseTable.action[s][analyseTable.getTerminalIndex(ch)] != "acc"){ //獲取字串 string str = analyseTable.action[s][analyseTable.getTerminalIndex(ch)]; //如果str為空,報錯並返回 if(str.size() == 0){ cout<<"出錯"; return ; } //獲取r或s後面的數字 stringstream ss; ss << str.substr(1); ss >> s; //如果是移進 if(str.substr(0,1) == "s"){ cout<<setw(10)<<step<<setw(10)<<vectTrancStr(0)<<setw(10)<<vectTrancStr(1)<<setw(10)<<vectTrancStr(2)<<setw(10)<<"A"<<"CTION["<<status.back()<<","<<ch<<"]=S"<<s<<","<<"狀態"<<s<<"入棧"<<endl; //輸入符號入棧 sign.push_back(ch); inputStr.erase(inputStr.begin()); //將狀態數字入棧 status.push_back(s); } //如果是歸約 else if(str.substr(0,1) == "r"){ //獲取第S個產生式 string formu = grammar.formula[s]; //cout<<s<<endl; int strSize = formu.size(); //將產生式轉化為字元陣列 char buf[100]; strcpy(buf,formu.c_str()); //獲取產生式的首字元 char nonTerCh = buf[0]; //獲取符號棧的出棧次數 int popCount = strSize - 3; //反向迭代 vector<int>::reverse_iterator rit = status.rbegin(); int i= 0; for(rit;rit != status.rend();rit++){ i++; if(i == popCount+1){ oldStatus = * rit; break; } } int r = s; //修改s s = analyseTable.goTo[oldStatus][analyseTable.getNonTerminalIndex(nonTerCh)]; cout<<setw(10)<<step<<setw(10)<<vectTrancStr(0)<<setw(10)<<vectTrancStr(1)<<setw(10)<<vectTrancStr(2)<<setw(10)<<"r"<<r<<(string)":"+grammar.formula[r]+(string)"歸約,GOTO{"<<oldStatus<<","<<nonTerCh<<")="<<s<<"入棧"<<endl; //對符號棧進行出棧和狀態棧進行出棧 for(int i=0 ;i< popCount;i++){ sign.pop_back(); status.pop_back(); } //再對產生式的開始符號入棧 sign.push_back(nonTerCh); //再把新的狀態入棧 status.push_back(s); } else{ //什麼都不處理 } //步驟數加1 step++; //獲取棧頂狀態 s = status.back(); //獲取輸入的字元 ch = inputStr.front(); } cout<<setw(10)<<step<<setw(10)<<vectTrancStr(0)<<setw(10)<<vectTrancStr(1)<<setw(10)<<vectTrancStr(2)<<setw(10)<<"A"<<"cc:分析成功"<<endl; }
-
實驗結果
對於正確的輸入串i+i*i執行結果如下:
對於不正確的輸入串i+i)執行結果如下: