【C++实现】编译原理 免考小队 FIRSTVT集生成算法
生活随笔
收集整理的這篇文章主要介紹了
【C++实现】编译原理 免考小队 FIRSTVT集生成算法
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
背景
期末考試免考,沖!
實(shí)驗(yàn)名稱
FIRSTVT集生成算法
實(shí)驗(yàn)時(shí)間
2020年6月3日 到 2020年6月9日
院系
信息科學(xué)與工程學(xué)院
組員姓名
Chocolate、kry2025、鐘先生、leo、小光
實(shí)驗(yàn)環(huán)境介紹
- windows 10 操作系統(tǒng)
- Eclipse 進(jìn)行 java 編程
- CodeBlocks 進(jìn)行 C++ 編程
實(shí)驗(yàn)?zāi)康呐c要求
目的
- 深刻理解FIRSTVT集生成算法
- 掌握FIRSTVT集生成的過(guò)程
- 加強(qiáng)團(tuán)隊(duì)合作能力
- 提高自身的編程能力和解決問(wèn)題的能力
要求
- 編程實(shí)現(xiàn)FIRSTVT集生成算法
- 算法簡(jiǎn)潔,不冗余
解決問(wèn)題
Firstvt集的求法,有三條規(guī)則:
(1)A->a…,即以終結(jié)符開頭,該終結(jié)符入Firstvt
(2)A->B…,即以非終結(jié)符開頭,該非終結(jié)符的Firstvt入A的Firstvt
(3)A->Ba…,即先以非終結(jié)符開頭,緊跟終結(jié)符,則終結(jié)符入Firstvt
實(shí)驗(yàn)結(jié)果
源代碼
#include<bits/stdc++.h> #define endl '\n' #define mst(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=1e3+5; class node{ public:string left;vector<string> right;node(const string& str){ //類似構(gòu)造函數(shù)left=str;right.clear();}void push(char str[]){ //放入產(chǎn)生式右部right.push_back(str);}void print(){ //打印產(chǎn)生式printf("%s->%s",left.c_str(),right[0].c_str());for(int i=1;i<right.size();i++)printf("|%s",right[i].c_str());puts("");} }; int n; char buf[maxn]; int used[maxn],vis[maxn]; vector<node> vnode; map<string,int> mp; vector<char> vt; set<char> firstVt[maxn]; //dfs搜索 void dfs(int x){if(vis[x]) return;vis[x]=1;string& left=vnode[x].left; //取出當(dāng)前產(chǎn)生式左部for(int i=0;i<vnode[x].right.size();i++){string& str=vnode[x].right[i]; //取出當(dāng)前產(chǎn)生式右部if(isupper(str[0])){ //如果產(chǎn)生式右部第一個(gè)為非終結(jié)符int y=mp[str.substr(0,1)]-1; //拿到對(duì)應(yīng)下標(biāo)if(str.length()>1 && !isupper(str[1])) //判斷第二個(gè)是否為終結(jié)符,是的話加入firstVt[x].insert(str[1]);dfs(y); //搜索當(dāng)前非終結(jié)符set<char>::iterator it = firstVt[y].begin();for(;it!=firstVt[y].end();it++) //加入非終結(jié)符y的firstVt集合firstVt[x].insert(*it);}else{firstVt[x].insert(str[0]); //如果是終結(jié)符,直接加入}} } void makeFirstVt(){memset(vis,0,sizeof(vis));for(int i=0;i<vnode.size();i++){if(vis[i]) continue;else dfs(i);}puts("------------FIRSTVT集-------------------");for(int i=0;i<vnode.size();i++){printf("%s : ",vnode[i].left.c_str() );set<char>::iterator it = firstVt[i].begin();for(;it!=firstVt[i].end();it++)printf("%c ",*it);puts("");} } //初始化工作,清空數(shù)組 void init(){memset(used,0,sizeof(used)); //初始化used數(shù)組,用于記錄VT集vt.clear(); //清空VT集合vnode.clear(); //清空產(chǎn)生式node集mp.clear(); //清空維護(hù)產(chǎn)生式下標(biāo)集for(int i=0;i<=maxn;i++) //清空輸出結(jié)果firstVt集firstVt[i].clear(); } int main(){while(cin>>n){init(); //初始化工作for(int i=0;i<n;i++){scanf("%s",buf); //輸入產(chǎn)生式int len=strlen(buf),j;for(j=0;j<len;j++)if(buf[j]=='-'){buf[j]=0;break;}string tmp=buf; //取產(chǎn)生式左部非終結(jié)符if(!mp[tmp]){vnode.push_back(node(tmp)); //去重操作mp[tmp]=vnode.size(); //維護(hù)下標(biāo)}int idx=mp[tmp]-1;vnode[idx].push(buf+j+2); //vnode加入產(chǎn)生式右部for(int k=0;k<j;k++){ //檢查產(chǎn)生式左部是否包含終結(jié)符if(!isupper(buf[k])){if(used[buf[k]]) continue;used[buf[k]]=1;vt.push_back(buf[k]);}}for(int k=j+2;k<len;k++){ //將產(chǎn)生式右部加入vt集合if(!isupper(buf[k])){if(used[buf[k]]) continue;vt.push_back(buf[k]);used[buf[k]]=vt.size();}}}puts("************VT集*******************");for(int i=0;i<vt.size();i++ )printf("%c ",vt[i]);puts("");cout<<endl;puts("*************產(chǎn)生式*****************");for(int i=0;i<vnode.size();i++)vnode[i].print();puts("************************************");cout<<endl;makeFirstVt(); //求FirstVt集}return 0; }輸出結(jié)果
測(cè)試樣例
8 E->E+T E->T T->T*F T->F F->P^F F->P P->(E) P->i參考文獻(xiàn)
參考:編譯原理(七) 算符優(yōu)先分析法(構(gòu)造算符優(yōu)先關(guān)系表算法及C++實(shí)現(xiàn))
總結(jié)
以上是生活随笔為你收集整理的【C++实现】编译原理 免考小队 FIRSTVT集生成算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: VMware报错:无法获得VMCI驱动程
- 下一篇: C++基于QT的模仿宝石迷阵游戏源码