1. 程式人生 > 其它 >基於SLR(1)分析法的語法制導翻譯及中間程式碼生成程式設計原理與實現

基於SLR(1)分析法的語法制導翻譯及中間程式碼生成程式設計原理與實現

前言:終於良心發現開始自己寫編譯原理實驗了,這不得來水一篇部落格?

參考:編譯原理:基於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集的時候偷懶了,直接面向文法程式設計。

寫完想象了一下整個編譯器的工作量,大受震撼。

完整程式碼:

#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;
}
View Code