前言:终于良心发现开始自己写编译原理实验了,这不得来水一篇博客?
参考:编译原理:基于SLR(1)分析法的语法制导翻译及中间代码生成
输入格式:
文法:
二元组:
函数介绍:
int main() { generate(); 调用实验一,生成二元组 readFileFromLab1(); 读取实验一生成文件 readGrammar(); 读取文法 getVnVt(); 分析终结符和非终结符 getFollow(); 分析Follow集 getDFA(); 自动生成DFA getSLRTable(); 根据DFA生成分析表 printSLRTable(); 打印分析表 if(analysisSLR()){ printf("分析成功!"); printRes(); 打印四元组 } else printf("分析失败QAQ"); return 0; }
DFA生成:
int isNotNewSt(status *a) 判断是否为新状态 status* getClosure(set<node>& content) 获取闭包 status* getStatus(const set<node>& a) 计算新增加一个字符后状态
主要数据存储方式:
vector<pair<int,string> > in; vector<pair<char, string> > grammar; set<char> vn,vt; map<char,set<char> > follow; map<char,pair<char,int> > slr[20]; 一个项目 struct node{ int pos; 下一个要读哪个字符 char from; 左式 string to; 右式 node(int p,char f,string t){ pos=p;from=f;to=t; }
为了塞到set里得有个小于号 bool operator < (const node &a) const{ if(pos==a.pos){ if(from==a.from) return to<a.to; return from<a.from; } return pos<a.pos; } bool operator == (const node &a) const{ if(pos==a.pos){ if(from==a.from) return to==a.to; } return false; } };
状态描述 struct status{ int id; 状态序号 set<node> content; 状态内项目集 bool accepted; 是否为终结状态 map<char,int> action; map<char,int> gotu; goto是关键字,所以换一个 bool operator == (const status &a) const{ if(content.size()==a.content.size()){ for(auto i:a.content){ if(!content.count(i)){ return false; } } return true; } return false; } }; 所有状态 vector<status*> allSt;
四元组 struct four{ string op,arg1,agr2,des; }; vector<four> res;
SLR分析表:
分析过程(太长不截了):
四元式:
求FOLLOW集的时候偷懒了,直接面向文法编程。
写完想象了一下整个编译器的工作量,大受震撼。
upd:四元式生成等号那有点问题,特判一下就行。就这样吧。摆烂.jpg
完整代码:
#include <bits/stdc++.h> #include "generator.h" using namespace std; vector<pair<int,string> > in; vector<pair<char, string> > grammar; set<char> vn,vt; map<char,set<char> > follow; map<char,pair<char,int> > slr[20]; struct node{ int pos; char from; string to; node(int p,char f,string t){ pos=p;from=f;to=t; } bool operator < (const node &a) const{ if(pos==a.pos){ if(from==a.from) return to<a.to; return from<a.from; } return pos<a.pos; } bool operator == (const node &a) const{ if(pos==a.pos){ if(from==a.from) return to==a.to; } return false; } }; struct status{ int id; set<node> content; bool accepted; map<char,int> action; map<char,int> gotu; bool operator == (const status &a) const{ if(content.size()==a.content.size()){ for(auto i:a.content){ if(!content.count(i)){ return false; } } return true; } return false; } }; vector<status*> allSt; struct four{ string op,arg1,agr2,des; }; vector<four> res; void readFileFromLab1(){ FILE *fp=fopen("test.txt", "r"); char s[10]; while(fscanf(fp,"%s",s)!=EOF){ int len=1,id=0; while(s[len]>='0'&&s[len]<='9'){ id=id*10+s[len]-'0'; len++; } len+=2; char s2[20]={0}; int cnt=0; while(s[len]!='\''){ s2[cnt++]=s[len]; len++; } in.push_back(make_pair(id,s2)); } fclose(fp); } void readGrammar(){ FILE *fp= fopen("gramma.txt","r"); char s[50]; while(fscanf(fp,"%s",&s)!=EOF){ char s1=s[0]; int len=3; while(1) { char s2[20]={0}; int cnt=0; while (s[len] != '|') { if(s[len]=='\0'){ grammar.push_back(make_pair(s1,s2)); goto nxt; } s2[cnt++]=s[len]; len++; } grammar.push_back(make_pair(s1,s2)); len++; if(len=='\0') break; } nxt:; } fclose(fp); } void getVnVt(){ vn.insert('S'); for(auto [_,i]:grammar) { for (int k = 0; k < i.length(); k++) { if (i[k] >= 'A' && i[k] <= 'Z') { vn.insert(i[k]); } else vt.insert(i[k]); } } } void getFollow() { follow['S'].insert('#'); for (auto[m, j]: grammar) { for (int i = 0; i < j.length() - 1; i++) { if (vn.count(j[i]) && vt.count(j[i + 1])) { follow[j[i]].insert(j[i + 1]); } } } for (auto[m, j]: grammar) { char end = j[j.length() - 1]; if (vn.count(end)) { for (auto i: follow[m]) { follow[end].insert(i); } } } } status* getClosure(set<node>& content){ bool accepted=true; set<char> clo; queue<char> q; for(auto [pos,from,to]:content){ if(vn.count(to[pos])){ if(!clo.count(to[pos])){ clo.insert(to[pos]); q.push(to[pos]); } } } while(!q.empty()){ char now=q.front(); q.pop(); for(auto[x,y]:grammar) { if (x == now) { content.insert(node(0, x, y)); if (vn.count(y[0])) { if (!clo.count(y[0])) { clo.insert(y[0]); q.push(y[0]); } } } } } for(auto [pos,from,to]:content){ if(pos!=to.size()) accepted=false; } status* res=new status; res->content=content; res->accepted=accepted; return res; } status* getStatus(const set<node>& a){ set<node> content; for(auto [pos,from,to]:a){ if(pos<to.length()) content.insert(node(pos+1,from,to)); } return getClosure(content); } int isNotNewSt(status *a){ for(int i=0;i<allSt.size();i++){ if(*allSt[i]==*a) return i; } return 0; } void getDFA(){ set<node> extra; extra.insert(node(0,'Z',"S")); status* begin=getClosure(extra); begin->id=0; queue<status*> q; q.push(begin); allSt.push_back(begin); map<char,int> vis; while(!q.empty()){ status* now=q.front(); q.pop(); vis.clear(); set<node> s; for(auto [pos,from,to]:now->content){ char temp=to[pos]; if(vis[temp]) continue; s.clear(); for(auto i:now->content){ if(i.to[i.pos]==temp&&i.pos<i.to.length()){ s.insert(i); } } if(s.empty()) continue; status* nxt=getStatus(s); int id; if(!(id=isNotNewSt(nxt))) { id=allSt.size(); if(!nxt->accepted) q.push(nxt); allSt.push_back(nxt); vis[temp]=1; } nxt->id=id; if (vn.count(temp)) now->gotu[temp] = nxt->id; if (vt.count(temp)) now->action[temp] = nxt->id; } } } int getPos(node a){ for(int j=0;j<grammar.size();j++){ if(grammar[j].first==a.from&&grammar[j].second==a.to){ return j; } } return 0; } void getSLRTable() { vt.insert('#'); for(int i=0;i<allSt.size();i++){ for(auto j:vt) slr[i][j].first='n'; for(auto j:vn) slr[i][j].first='n'; } for(int i=0;i<allSt.size();i++){ for(auto j:allSt[i]->content){ if(j.pos==j.to.length()){ if(j.from=='Z') { slr[i]['#'].first='a'; continue; } for(auto k:follow[j.from]) { slr[i][k].first = 'r'; slr[i][k].second = getPos(j); } } } } for (int i = 0; i < allSt.size(); i++) { if(allSt[i]->accepted){ node a=*(allSt[i]->content.begin()); int id= getPos(a); for(auto j:follow[a.from]){ slr[i][j].first='r'; slr[i][j].second=id; } } for(auto [x,y]:allSt[i]->action){ slr[i][x].first='s'; slr[i][x].second=y; } for(auto [x,y]:allSt[i]->gotu){ slr[i][x].first='g'; slr[i][x].second=y; } } } void printSLRTable(){ printf(" | "); for(auto i:vt) printf("%c ",i); printf("| "); for(auto i:vn) printf("%c ",i); printf("\n"); for(int i=1;i<=14;i++) printf("-----"); printf("\n"); for(int i=0;i<allSt.size();i++){ printf("%-2d | ",i); for(auto j:vt){ if(slr[i][j].first=='a') printf("acc "); else if(slr[i][j].first=='n') printf(" "); else printf("%c%-2d ",slr[i][j].first,slr[i][j].second); } printf("| "); for(auto j:vn){ if(slr[i][j].first=='n') printf(" "); else printf("%-2d ",slr[i][j].second); } printf("\n"); } } int analysisSLR(){ stack<int> st; stack<char> ch; stack<string> ch2; auto printStack=[&st,&ch,&ch2](char nxt){ stack<char> t2=ch; vector<char> t1; while(!t2.empty()){ t1.push_back(t2.top()); t2.pop(); } reverse(t1.begin(),t1.end()); printf("char :["); for(auto i:t1) printf("%c",i); printf("\tnext:%c\n",nxt); stack<int> t3=st; t1.clear(); while(!t3.empty()){ t1.push_back(t3.top()); t3.pop(); } reverse(t1.begin(),t1.end()); printf("status:["); for(auto i:t1) printf("%d ",i); printf("\n\n"); }; st.push(0); ch.push('#'); ch2.push("#"); int i=0; int cnt=1; while(!st.empty()){ if(i>in.size()) return 0; char nxt; string nxtName; if(i<in.size()) { auto[id, name]=in[i]; nxt = id == 12 ? 'i' : name[0]; nxtName=name; } else nxt='#'; printStack(nxt); char sta=slr[st.top()][nxt].first; if(sta=='n') { printf("error at %d.",i); return 0; } if(sta=='s'){ int now=slr[st.top()][nxt].second; st.push(now); ch.push(nxt); ch2.push(nxtName); i++; } if(sta=='r'){ int num=slr[st.top()][nxt].second; int len=grammar[num].second.length()-1; int flag1=grammar[num].second.find('+')!=-1||grammar[num].second.find('-')!=-1|| grammar[num].second.find('*')!=-1||grammar[num].second.find('/')!=-1|| grammar[num].second.find('=')!=-1; int flag2=grammar[num].second.find('(')!=-1||grammar[num].second.find(')')!=-1; string temp[4];int cnt2=0; while(ch.top()==grammar[num].second[len]){ if(flag1){ temp[cnt2++]=ch2.top(); ch2.pop(); } if(flag2){ temp[cnt2++]=ch2.top(); ch2.pop(); } ch.pop(); st.pop(); len--; } if(flag1) { ch2.push("T" + to_string(cnt++)); res.push_back({temp[1],temp[0],temp[2],ch2.top()}); } if(flag2) ch2.push(temp[1]); ch.push(grammar[num].first); st.push(slr[st.top()][ch.top()].second); } if(sta=='a'){ return 1; } } return 0; } void printRes(){ printf("生成四元式:\n"); for(auto[a,s,d,f]:res){ cout<<'('+a+','+s+','+d+','+f+')'<<endl; } } int main() { generate(); readFileFromLab1(); readGrammar(); getVnVt(); getFollow(); getDFA(); getSLRTable(); printSLRTable(); if(analysisSLR()){ printf("分析成功!"); printRes(); } else printf("分析失败QAQ"); return 0; }