【編譯原理】c++實現自下而上語法分析及中間代碼(四元式)生成

寫在前面:本博客爲本人原創,嚴禁任何形式的轉載!本博客只容許放在博客園(.cnblogs.com),若是您在其餘網站看到這篇博文,請經過下面這個惟一的合法連接轉到原文!html

本博客全網惟一合法URL:http://www.cnblogs.com/acm-icpcer/p/9173880.htmlios

 

 

  基於C++語言實現的PL/0語言的算術表達式的自下而上的語法分析程序。該語言的其餘語法實現思想與此一致,故不贅述。c++

  運行此程序前,必須先將代碼經過:【編譯原理】c++實現詞法分析器的詞法分析,生成詞法表(詞法表是txt文件,爲了語法分析成功,務必刪除文件中最後空着的一行,即文件末尾不能夠留空白行)。生成的該詞法表爲此程序的必要輸入。git

  產生式:github

  S->X(AX)*|AX(AX)*
    X->Y(MY)*
    Y->I|N|(S)
    A->+|-
    M->*|/
    C->=|#|<|<=|>|>=
web

  本次的代碼主要是在【編譯原理】c++實現自下而上語法分析器的基礎上,伴隨着歸約的過程,增長了生成四元式的過程,也就是一邊歸約一邊生成中間代碼。設計模式

 

Talk is cheap, show you my source code:ide

/*
this code was first initiated by TZ,COI,HZAU
contact email:xmb028@163.com
personal website:wnm1503303791.github.io
personal blogs:www.cnblogs.com/acm-icpcer/
this code has been posted on my personal blog,checking url:www.cnblogs.com/acm-icpcer/p/9173880.html
Copyright 2018/6/12 TZ.
All Rights Reserved.
*/

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<iostream>  
#include<string>  
#include<vector>  
#include<stack>  
#include<bitset>  
#include<cstdlib>  
#include<cmath>  
#include<set>  
#include<list>  
#include<deque>  
#include<map>  
#include<queue>  
#include<fstream>
using namespace std;

//預處理函數 
bool preproccess(char *a,char *b,char *c)
{
    int i1=0,i2=1;//i2爲原串指針 
    memset(b,1024,'\0');
    while(a[i2]!=',')
    {
        b[i1]=a[i2];
        ++i1,++i2;
    }
    b[i1]='\0';
    
    i1=0;i2++;
    while(a[i2]!=')')
    {
        c[i1]=a[i2];
        ++i1,++i2;
    }
    c[i1]='\0';
    //cout<<b<<endl;
    return true;
}

fstream f2("stack.txt", ios::out);//打開文件,供寫 
fstream f3("quaternary.txt", ios::out);//打開文件,供寫 
static int mcount=1;//存儲打印次數 
//當移進或者歸約時打印棧內狀況,以供分析 
bool outf(int head,char data[1024][1024],fstream &f)
{
    f<<"times("<<mcount<<"),";
    f<<"head is:"<<head<<endl;
    for(int i=head;i>=0;i--)
    {
        f<<data[i]<<endl;
    }
    mcount++;
    f<<endl;
    return true;
}
//四元式寫入文件函數1 
bool outf2(int top,char dt[1024][1024],fstream &f)
{
    /*
    char arg1[1024],arg2[1024],op[1024];
    memset(arg1,sizeof(arg1),'\0');
    strcpy(arg1,dt[top]);
    memset(op,sizeof(op),'\0');
    strcpy(op,dt[top-1]);
    memset(arg2,sizeof(arg2),'\0');
    strcpy(arg2,dt[top-2]);
    
    f<<"("<<op<<","<<arg1<<","<<arg2<<","<<"T"<<")"<<endl;
    */
    f<<"("<<dt[top-1]<<","<<dt[top]<<","<<dt[top-2]<<","<<"T"<<")"<<endl;
    return true;
}
//四元式寫入文件函數2
bool outf3(int top,char dt[1024][1024],fstream &f)
{
    f<<"("<<dt[top-1]<<","<<dt[top]<<","<<"-"<<","<<"T"<<")"<<endl;
    return true;
}
//四元式寫入文件函數3
bool outf4(int top,char dt[1024][1024],fstream &f,char T)
{
    f<<"("<<":="<<","<<dt[top]<<","<<"-"<<","<<T<<")"<<endl;
    return true;
}

//「策略」設計模式,面向對象方法 
class presentation
{
private:
    char data[1024][1024];//
    char dt[1024][1024];//四元式棧 
    fstream *infile;//詞法分析表 
    int head,top;//兩個棧的棧頂指針 
public:
    //first initiated the object
    presentation(fstream *in_f)
    {
        this->infile=in_f;
        memset(data,sizeof(data),'\0');
        memset(dt,sizeof(dt),'\0');
        head=top=-1;
    }
    bool push()
    {
        head++;
        top++;
        
        infile->getline(data[head],1024);
        char t1[1024],t2[1024];//存放字符標誌
        preproccess(data[head],t1,t2);
        
        cout<<data[head]<<","<<t1<<endl;
        
        memset(data[head],1024,'\0');
        strcpy(data[head],t1);
        
        memset(dt[top],1024,'\0');
        strcpy(dt[top],t2);
        cout<<dt[top]<<","<<t2<<endl;
    }
    
    /*
    S->X(AX)*|AX(AX)*
    X->Y(MY)*
    Y->I|N|(S)
    A->+|-
    M->*|/
    C->=|#|<|<=|>|>= 
    */
    //歸約函數 
    bool reduce()
    {
        //S->X(AX)*|AX(AX)*
        if(    head>=4&&
              (!strcmp(data[head],"X"))&&
              (!strcmp(data[head-1],"plus")||!strcmp(data[head-1],"minus"))&&
              (!strcmp(data[head-2],"X"))&&
              (!strcmp(data[head-3],"plus")||!strcmp(data[head-3],"minus"))&&
              (!strcmp(data[head-4],"X"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            memset(data[head-2],1024,'\0');
            memset(data[head-3],1024,'\0');
            memset(data[head-4],1024,'\0');
            head=head-5+1;
            
            strcpy(data[head],"S");//歸約 
            /*
            stack description:
            top->     arg
                      op
            top-2->     arg
                     op
                      arg
            */
            if(outf2(top,dt,f3)&&outf2(top-2,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        if(    head>=2&&
              (!strcmp(data[head],"X"))&&
              (!strcmp(data[head-1],"plus")||!strcmp(data[head-1],"minus"))&&
              (!strcmp(data[head-2],"X"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            memset(data[head-2],1024,'\0');
            head=head-3+1;
            
            strcpy(data[head],"S");
            if(outf2(top,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        if(    head>=2&&/*top>=3*/
              (!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
              (!strcmp(data[head-1],"X"))&&
              (!strcmp(data[head-2],"plus")||!strcmp(data[head-2],"minus"))&&
              (!strcmp(data[head-3],"X"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            memset(data[head-2],1024,'\0');
            memset(data[head-3],1024,'\0');
            head=head-3+1;
            
            strcpy(data[head],"S");
            if(outf3(top,dt,f3)&&outf3(top-2,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        if(    head>=1&&
            (!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
            (!strcmp(data[head-1],"X"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            head=head-2+1;
            
            strcpy(data[head],"S");
            if(outf3(top,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        //X->Y(MY)*
        if(    head>=4&&
              (!strcmp(data[head],"Y"))&&
              (!strcmp(data[head-1],"times")||!strcmp(data[head-1],"slash"))&&
              (!strcmp(data[head-2],"Y"))&&
              (!strcmp(data[head-3],"times")||!strcmp(data[head-3],"slash"))&&
              (!strcmp(data[head-4],"Y"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            head=head-5+1;
            
            strcpy(data[head],"X");
            /*
            current stack description:
            top->     arg
                      op
            top-2->     arg
                     op
                      arg
            */
            if(outf2(top,dt,f3)&&outf2(top-2,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        if(    head>=2&&
              (!strcmp(data[head],"Y"))&&
              (!strcmp(data[head-1],"times")||!strcmp(data[head-1],"slash"))&&
              (!strcmp(data[head-2],"Y"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            memset(data[head-2],1024,'\0');
            head=head-3+1;
            
            strcpy(data[head],"X");
            /*
            current stack description:
                top->arg
                      op
                      arg
            */
            if(outf2(top,dt,f3))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            
            return true;
        }
        
        if(    head>=0&&(!strcmp(data[head],"Y"))
          )
        {
            memset(data[head],1024,'\0');
            head=head-1+1;
            
            strcpy(data[head],"X");
            if(outf4(top,dt,f3,'X'))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            return true;
        }
        
        //Y->I|N|(S)
        if(    head>=0&&(!strcmp(data[head],"ident"))
          )
        {
            memset(data[head],1024,'\0');
            head=head-1+1;
            
            strcpy(data[head],"Y");
            if(outf4(top,dt,f3,'Y'))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            return true;
        }
        
        if(    head>=0&&(!strcmp(data[head],"number"))
          )
        {
            memset(data[head],1024,'\0');
            head=head-1+1;
            
            strcpy(data[head],"Y");
            if(outf4(top,dt,f3,'Y'))
            {
                top==-1;
                memset(dt,sizeof(dt),'\0');
            }
            return true;
        }
        
        if(    head>=2&&
            (!strcmp(data[head],"rparen"))&&
            (!strcmp(data[head-1],"S"))&&
            (!strcmp(data[head-2],"lparen"))
          )
        {
            memset(data[head],1024,'\0');
            memset(data[head-1],1024,'\0');
            memset(data[head-2],1024,'\0');
            head=head-3+1;
            
            strcpy(data[head],"Y");
            return true;
        }
        
        return false;
    }
    //遍歷棧 
    bool visit_data()
    {
        cout<<"current stack:"<<endl;
        for(int i=head;i>=0;i--)
        {
            cout<<data[i]<<endl;
        }
        return true;
    }
    //主控函數 
    bool mainf()
    {
        while(!infile->eof())
        {
            push();
            bool t=reduce();
            outf(head,data,f2); 
            //每當移進結束時就檢查一下是否有可規約串 
            while(t)//防止規約嵌套 
            {
                t=reduce();
                outf(head,data,f2); 
            }
            //visit_data();
        }
        
        visit_data();
        
        bool flag=false;
        for(int i=head;i>=0;i--)
        {
            if(!strcmp(data[i],"S"))
            {
                flag=true;
            }
            if(    strcmp(data[i],"S")&&
                strcmp(data[i],"X")&&
                strcmp(data[i],"A")&&
                strcmp(data[i],"Y")&&
                strcmp(data[i],"M")&&
                strcmp(data[i],"C")
              )
            {
                return false;
            }
        }
        
        return flag;
        
        /*
        while(head>0)
        {
            bool t=reduce();
            //每當移進結束時就檢查一下是否有可規約串 
            while(t)//防止規約嵌套 
            {
                t=reduce();
            }
            //visit_data();
            outf(head,data,f2); 
        }
        */
    }
};

int main()
{
    fstream f1;
    f1.open("lexical.txt", ios::in);//打開詞法分析表,供讀
    
    presentation* s1=new presentation(&f1);
    bool result=s1->mainf();
    
    if(result)
        cout<<"ACCEPTED!"<<endl;
    else
        cout<<"ERROR!"<<endl;
    
    f1.close();
    f2.close();
    return 0;
}

 

運行示例:
函數

(1)合法的語句:post

 

(2)不合法的語句:

 

 

 

tz@COI HZAU

2018/6/12

相關文章
相關標籤/搜索