c++简单实现SLR1文法分析器(自动求项目集、建表、分析)

c++简单实现SLR1文法分析器(自动求项目集、建表、分析)_第1张图片

c++简单实现SLR1文法分析器(自动求项目集、建表、分析)_第2张图片

 

 

 

 

 

c++简单实现SLR1文法分析器(自动求项目集、建表、分析)_第3张图片

 

c++简单实现SLR1文法分析器(自动求项目集、建表、分析)_第4张图片

 

c++简单实现SLR1文法分析器(自动求项目集、建表、分析)_第5张图片

 

 

  1. 规定终结符用小写字母开头和后面接若干“`”表示例如a,b,i,i`,i``表示不同的终结符。非终结符用大写字母和后面接若干“`”表示非终结符例如A,B,T`,T``表示不同的非终结符。用“&”代表空串。连续输入的“-”“>”代表推导,分割产生式左右部。输入的文法的第一个产生式为文法开始符的产生式。
  2. 设置变量SIZE,代表非终结符的最大的数量。对终结符和非终结符进行编号,规定数值0为空串(&)。用1~SIZE的正整数对终结符和非终结符分别进行编号。为了在候选式中不发生冲突,候选式的终结符使用终结符的相反数。例如:编号A:1, B:2, a:1, b:2 。则二维数组{{1,2},{-1,2},{0} } 代表候选式 AB | aB | & 。FIRST和FOLLOW集合存储的是非终结符的编号和终结符的编号的相反数。
  3. 将候选式分开存储进pro结构体中,属性Vn表示产生式左部,candy数组表示产生式右部。都是存储符号的编号。每个pro的下标代表产生式的编号。项目集结构体中属性pro集合代表一对序偶一个代表产生式的编号,一个表示‘.’号的位置。集合v代表项目集的边。go集合也是一对序偶,第一个数表示边代表的字符编号,第二个数代表指向的项目集。

 

 

#include 


using namespace std;

#include "definition.h"
#include "Check.h"
#include "Init.h"
#include "getFirst.h"
#include "getFollow.h"
#include "Display.h"
#include "getI.h"
#include "getTable.h"
#include "analyse.h"

int main()
{

    ifstream file;
    file.open("test/input3.txt");
    string str;
    while(getline(file, str)){  //输入一行,即一个非终结符的候选式
        cout<

 

#ifndef DEFINITION_H_INCLUDED
#define DEFINITION_H_INCLUDED

#define SIZE 100

int idVt = 0;   //终结符编号
int idVn = 1;   //非终结符编号,0号为扩展文法开始符
int idPro = 1;   //产生式编号,0号为扩展文法开始符

int JING;   //# 号
int EMPTY = 5*SIZE;  //空串
int startVt = -1;   //判断是否处理了开始符,只处理一次
int ERROR = 4*SIZE; //出错标志
int ACC = 5*SIZE;   //成功标志

mapmpVn,mpVt;   //编号(字符,编号)
maprmpVn,rmpVt; //双向映射(编号,字符)

//存储分开编号的产生式,下标为编号
struct Pro {
    int Vn; //产生式左部 1 <=> A
    vectorcandy;   //产生式右部{1,2,-1} 代表 A -> ABa
    Pro(){
        Vn =0 ;
        candy.clear();
    }
}pro[SIZE];

//项目集I
struct Ix{
    set >pro;  //记录项目集拥有的产生式编号以及对应的‘.’ 号的位置  {idPro,dot} 例如: {  {0,0} , {1,1}   }  <=> { S`->.XX, E -> X.XX  }
    setv;  //记录项目集的边的符号的编号如:a编号1。GOTO(a,I)、GOTO(b,I) 的a, b
    set >go;  //(idVt/idVn, numI)    对应的边以及其GOTO到的项目集
    void Clear(){
        pro.clear();
        v.clear();
        go.clear();
    }
}I[SIZE];

//每个非终结符对应一个结构体
struct NoTml
{
    vector > pro;   //候选式:例如 {{1,2},{-1,2},{0} } => AB | aB | &
    set FIRST, FOLLOW; //FIRST集,FOLLOW集
    int proNum; //处理FIRST集时使用,判断以及完成的候选式
    bool FirstFinish;   //处理FIRST集时使用,判断是否全部候选式都完成
    NoTml(){
        FirstFinish = false;
        int proNum = 0 ;
        FIRST.clear();
        FOLLOW.clear();
        pro.clear();
    }
}notml[SIZE];   //每个下标对应一个非终结符


#endif // DEFINITION_H_INCLUDED
#ifndef INIT_H_INCLUDED
#define INIT_H_INCLUDED

void init(string str){
    int len = str.length();
    int pos = 0;
    int idLeft = 0;
    string word="";
    vectorvec;

    //获取产生式左部
    while(pos='A'&&str[pos]<='Z'){ //判断是否为大写字母开始,即是否为非终结符
            word="";
            word+=str[pos];
            pos++;
            while(pos') {
            idLeft = mpVn[word];
            pos+=2;
            break;
        }
        else {
            errorG();   //文法输入错误
            return ;
        }
    }

    //扩展文法开始符
    if(startVt == -1){
        rmpVt[EMPTY]="&"; //& 代表空串
        mpVt["&"] = EMPTY;

        JING = idVt++;    //对 # 号进行编号
        rmpVt[JING]="#";
        mpVt["#"] = JING;

        ERROR = SIZE+1;

        startVt = idLeft;
        mpVn["S`"] = 0;
        rmpVn[0] = "S`";
        pro[0].candy.push_back(idLeft);
        pro[0].Vn = 0;

        notml[0].pro.push_back({idLeft});


    }

    //获取产生式右部
    while(pos='A'&&str[pos]<='Z') {    //对非终结符编号
            word="";
            word+=str[pos];
            pos++;
            while(pos='A'&&str[pos]<='Z')){    //对终结符编号
            word="";
            word+=str[pos];
            pos++;
            while(pos=SIZE||idVn>=SIZE) { //终结符或,非终结符超出范围,错误
        errorG();
        return ;
    }

}

#endif // INIT_H_INCLUDED

 

#ifndef GETFIRST_H_INCLUDED
#define GETFIRST_H_INCLUDED

//输出FIRST集合
void dispalyFirst(){
    cout<<"---------------FIRST start---------------------"<::iterator it=notml[i].FIRST.begin();it!=notml[i].FIRST.end();it++){
            cout< Y...的FIRST(Y)/{&}加入到FIRST(X)
    for(int i=0;i0){   //判断首字符是否为非终结符
                settmp;
                int idk=notml[i].pro[j][0]; //获取首字符的编号
                tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
                if(tmp.count(EMPTY)) tmp.erase(EMPTY);
                notml[i].FIRST.insert(tmp.begin(),tmp.end());
            }
        }
    }

    //规则(2)第二步,每次有变化都要进行更新
    bool hasChange = true;
    int Empty=0;
    while(hasChange){
        hasChange = false;
        for(int i=0;i0&&!notml[id].FirstFinish){   //必须是已经处理完成的非终结符才能更新现在的非终结符
                            ok=false;
                            break;
                        }
                    }
                    if(ok){ //对非终结符进行更新
                        for(int k=0;k0&¬ml[id].FirstFinish){
                                set tmp;
                                tmp.insert(notml[id].FIRST.begin(),notml[id].FIRST.end());  //将FIRST(Y)加入到FIRST(X)
                                if(notml[id].FIRST.count(EMPTY)){   //判断空串
                                    Empty++;
                                    tmp.erase(EMPTY);
                                    notml[i].FIRST.insert(tmp.begin(),tmp.end());
                                    hasChange = true;
                                }
                                else {
                                    notml[i].FIRST.insert(tmp.begin(),tmp.end());
                                    hasChange = true;
                                    break;  //没有空串则停止
                                }
                            }
                        }
                        if(Empty == notml[i].pro[j].size()){    //如果全部字符都有空串,则加入空串到FIRST(X)
                            notml[i].FIRST.insert(EMPTY);
                        }
                        notml[i].proNum++;  //记录已经处理候选式
                        if(notml[i].proNum == notml[i].pro.size()) notml[i].FirstFinish = true; //全部候选式处理完则该非终结符处理完
                    }
                }
            }
        }
    }
}


#endif // GETFIRST_H_INCLUDED

 

#ifndef GETFOLLOW_H_INCLUDED
#define GETFOLLOW_H_INCLUDED

//输出FOLLOW集合
void dispalyFollow(){
    cout<<"---------------FOLLOW start---------------------"<::iterator it=notml[i].FOLLOW.begin();it!=notml[i].FOLLOW.end();it++){
            cout< aBP 将FIRST(P)/{&} 加入到FOLLOW(B)
    for(int id=0;id0)){
                        settmp;
                        int idk = notml[i].pro[j][k+1];
                        tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
                        if(tmp.count(EMPTY))
                            tmp.erase(EMPTY);
                        notml[id].FOLLOW.insert(tmp.begin(),tmp.end()); //FIRST(P)/{&}加入FOLLOW(A)
                    }
                }
            }
        }
    }

    //规则(3)A -> aB  或  A-> aBP
    queueque;  //记录需要进行处理的非终结符
    for(int i=1;i aB
                        if(notml[i].FOLLOW.size()==0) que.push(id);
                        else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
                    }
                    else if((notml[i].pro[j][k]==id)&&(k+10)&&(notml[notml[i].pro[j][k+1]].FIRST.count(0)>0)){
                        //候选式为  A -> aBP
                        if(notml[i].FOLLOW.size()==0) que.push(id);
                        else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
                    }
                }
            }
        }
    }
}


#endif // GETFOLLOW_H_INCLUDED

 

#ifndef GETI_H_INCLUDED
#define GETI_H_INCLUDED

//处理项目集

stackst;   //记录需要增长的项目集
bool vis[SIZE]; //标志每次扩展一个项目集的产生式,判断是否重复

int numI = 0;   //项目集的数量
Ix tmpI;    //项目集的临时变量

//显示每个项目集
void displayByIdI(int id){
    cout<<"-----------------start---------------------"< x : I[id].pro){
        int idV = x.first;
        int dot = x.second;
        int idV2 = pro[idV].Vn;
        flag = false;
        cout<";
        for(int j=0;j0){
                cout< x:I[id].go){
        cout<<"GOTO(";
        if(x.first>0){
            cout< p:I[i].pro){
//            cout< p:I[i].go){
//            cout<0){
                Closure(pro[i].candy[0]);   //根据第一个字符继续搜索
            }
        }
    }

}

//求项目集
void GOTO(int idV,int dot){
    memset(vis, false, sizeof(vis));    //每次处理一个项目集要将产生式标志清零
    tmpI.pro.insert({idV, dot+1});      //存储产生式以及它的点‘.’位置
    if(dot+1 x:I[0].pro){
        int idV = x.first;
        int dot = x.second;
        int Vn = pro[idV].candy[dot];
        I[0].v.insert(Vn);
    }

    //使用栈存储需要增长的项目集,从0号项目集开始
    st.push(0);
    while(!st.empty()){
        int idI = st.top();     //获取项目集编号
        st.pop();
        for(int x:I[idI].v){    //遍历项目集的出度边
            tmpI.Clear();       //初始化临时遍历,用来指定下一个扩展的节点
            for(pair p:I[idI].pro){    //遍历项目集的产生式
                int idV = p.first;
                int dot = p.second;
                int v = pro[idV].candy[dot];
                if(x == v){                 //产生式的点‘.’后面的字符是出度的边的字符则边指向另一个项目集
                    GOTO(idV, dot);
                }
            }
            I[idI].go.insert({x,getNext()});    //增加一条边
        }
    }

    //输出项目集
    for(int i=0;i<=numI;i++){
        displayByIdI(i);
        cout<

 

#ifndef GETACTION_H_INCLUDED
#define GETACTION_H_INCLUDED

//求ACTION和GOTO表

int Action[SIZE][SIZE];     //第一维表示项目集编号,第二维表示终结符或非终结符
int Goto[SIZE][SIZE];

//显示表内容
void displayTable(){

    cout<<"------------------------------LR Table-----------------------------"<=2*SIZE){
                    cout<<"r"<p:I[i].pro){   //遍历其全部产生式
            idP = p.first;
            dot = p.second;

            if(pro[idP].candy.size()==dot&&idP==0){   //规则(3) 处理文法开始符,如S` -> S
                Action[i][JING]=ACC;
            }
            else if(pro[idP].candy.size()==dot){    //规则(2) 处理点‘.’在产生式最右边  如A -> a .
                for(int j=0;j x:I[i].go){   //遍历每条边
                    int idt = x.first;  //边的字符 a
                    int idI = x.second; //边的指向项目集 I
                    if(idt>0){  //点‘.’后面是非终结符 如A -> a . Bp
                        Goto[i][idt] = idI;
                    }
                    else if(pro[idP].candy.size()>dot&&(pro[idP].candy[dot]==idt)){    //点‘.’后面是终结符  如A -> c . ap
                        Action[i][-idt] = idI;
                    }
                }
            }

        }


    }
    displayTable();
}

#endif // GETACTION_H_INCLUDED

 

#ifndef ANALYSE_H_INCLUDED
#define ANALYSE_H_INCLUDED

//输出ACTION动作
void displayS(int inNum,int stzNum,int stfNum,int tableNum){
    cout<<"ACTION["<";
    for(int i=0;i0) cout<st){
    vectorvec;
    while(!st.empty()){
        vec.push_back(st.top());
        st.pop();
    }
    for(int i=vec.size()-1;i>=0;i--){
        if(i==0) cout.width(20-2*vec.size());
        cout<st){
    vectorvec;
    while(!st.empty()){
        vec.push_back(st.top());
        st.pop();
    }
    for(int i=vec.size()-1;i>=0;i--){
        if(i==0) cout.width(20-2*vec.size());
        if(vec[i]>0) cout< vec){
    for(int i=pos;i0) cout<input;
    for(int i=0;istz, stf; //状态栈和符号栈

    stz.push(0);
    stf.push(-JING);

    int pos = 0;

    int step = 1;
    while(1){
        cout.width(8);
        cout<=2*SIZE){   //归约
            int idP = tableNum - 2*SIZE;
            for(int i=pro[idP].candy.size()-1;i>=0;i--){    //根据产生式右部进行出栈
                if(pro[idP].candy[i]!=stf.top()) errorA();
                if(stf.size()==0||stz.size()==0){
                    errorA();
                    return ;
                }
                stf.pop();
                stz.pop();

            }
            stf.push(pro[idP].Vn);  //将产生式左部加进符号栈
            if(stf.size()==0||stz.size()==0){
                errorA();
                return ;
            }
            int stzT = stz.top();
            int stznew = Goto[stzT][pro[idP].Vn];   //取得对应的GOTO表值
            stz.push(stznew);   //将GOTO表的值加入状态栈
            displayR(stzT,tableNum,idP,stznew); //输出归约动作
        }else{     //移进
            stz.push(tableNum);
            stf.push(inNum);
            pos++;
            displayS(inNum,stzNum,stfNum,tableNum);
        }
        cout<

 

#ifndef CHECK_H_INCLUDED
#define CHECK_H_INCLUDED

void errorG()
{
    cout<<"输入的文法有误"<
#ifndef DISPLAY_H_INCLUDED
#define DISPLAY_H_INCLUDED

void displayPro2(){
    for(int i=0;i ";
        for(int j=0;j< notml[i].pro.size();j++){
             for(int k=0;k0)
                    cout<";
        for(int x : pro[i].candy){
            if(x>0){
                cout<

 

你可能感兴趣的:(编译原理)