【编译原理】LR(1)语法分析器 c++代码

转载自:https://www.ccppcoding.com/archives/197040 大神

#include<fstream>
#include<iostream>
#include<string>
#include<vector>
#include <algorithm>

#define MAX_Count 100

#include <set>
#include <stack>
#include <iomanip>
#include <sstream>
#include <string>
#include<cstring>
#include <map>

using namespace std;


// 重载一下+号运算符
template<typename CSS_LR1>
vector<CSS_LR1> &operator+(vector<CSS_LR1> &v1, vector<CSS_LR1> &v2) {
    v1.insert(v1.end(), v2.begin(), v2.end());
    return v1;
}


struct VN_Set {
    string VN_name;//非终结符
    set<string> FIRST; //First集合
    set<string> FOLLOW;
};
struct CSS {
    string start;//非终结符
    vector<string> next; //First集合
};

struct CSS_LR1 {
    string start;//非终结符
    vector<string> next; //First集合
    int num;
    vector<string> tail;

//
//    bool operator==(CSS_LR1& rhs) const {
//        return (start == rhs.start &&
//                next == rhs.next &&
//                num == rhs.num &&
//                tail == rhs.tail);
//    }
    bool operator==(const CSS_LR1 &rhs) {
        return (start == rhs.start &&
                next == rhs.next &&
                num == rhs.num &&
                tail == rhs.tail);
    }

};

int CSSCount = 0;
CSS css[MAX_Count];//产生式
VN_Set VN_First[MAX_Count];//非终结符集的First集合
set<string> VN;// 非终结符集合
set<string> VT;//终结符集合
int I_count = 0;//记录LR1项目数
vector<CSS_LR1> I[MAX_Count]; //项目集
map<string, int> mark_Follow;//用于标记Follow 防止套娃
map<string, int> GOTO[MAX_Count];
map<string, string> ACTION[MAX_Count];


bool cmp_vector(vector<CSS_LR1> &v1, vector<CSS_LR1> &v2) {
    if (v1.size() != v2.size()) return false;
    for (int i = 0; i < v2.size(); i++) {
        CSS_LR1 t;
        t = v2[i];
        vector<CSS_LR1>::iterator result = find(v1.begin(), v1.end(), t); //查找3
        if (result == v1.end()) //没找到
            return false;
    }
    return true;
}

/*
*实现编译原理语法分析中计算非终结符的First集Follow集
*/
set<string> get_FIRST(string a) { //求First集合
    set<string> T;
    for (int i = 0; i < CSSCount; i++) {
        if (css[i].start == a) {  // a->..
            for (int j = 0; j < css[i].next.size(); j++) {
                if (VT.find(css[i].next[j]) != VT.end()) { //是终结符开头
                    T.insert(css[i].next[j]);
//    T.erase("*");
                    break;
                } else {
                    if (css[i].next[j] == css[i].start) {
                        break;
                    }
                    set<string> U = get_FIRST(css[i].next[j]);
                    T.insert(U.begin(), U.end());
                    if (U.find("$") != U.end()) { //U中含有*,继续查下个的first
                        if (j != css[i].next.size() - 1)
                            T.erase("$");
                    } else {

                        break;
                    }
                }


            }

        }
    }

    return T;
}

set<string> get_FOLLOW(string a) {
    set<string> T;
//cout<<"现在在求"<<a<<" 的Follow"<<endl;
    mark_Follow[a]++;
    if (mark_Follow[a] >= 2) {
        return T;
    }

    set<string> temp;
    if (a == css[0].start) {
        T.insert("#");
    }
    for (int i = 0; i < CSSCount; i++) {
        for (int j = 0; j < css[i].next.size(); j++) {
            if (VT.find(css[i].next[j]) == VT.end() && a == css[i].next[j]) { //是非终结符,求FOLLOW集合
                if (j == css[i].next.size() - 1 && a != css[i].start) {//S->...a
                    set<string> tt = get_FOLLOW(css[i].start);
                    T.insert(tt.begin(), tt.end());
                }
                for (int k = j + 1; k < css[i].next.size(); k++) {
                    if (VT.find(css[i].next[k]) != VT.end()) {//后面一个是终结符  S->..av..
                        T.insert(css[i].next[k]);
                        break;
                    } else {
                        temp = get_FIRST(css[i].next[k]);
                        if (temp.find("$") != temp.end()) {//有$ S->..a B..
                            T.insert(temp.begin(), temp.end());
                            T.erase("$");
                            if (k == css[i].next.size() - 1) { //S->..a B
                                set<string> tt = get_FOLLOW(css[i].start);
                                T.insert(tt.begin(), tt.end());
                                break;
                            }
                        } else {
                            T.insert(temp.begin(), temp.end());
                            break;
                        }
                    }
                }

            }
        }

    }
//cout<<a<<" "<<mark_Follow[a]<<endl;
    mark_Follow[a] = 0;
    return T;
}


void GetFirst_and_Follow() {
    set<string>::iterator it;
    int count = 0;
    cout << "=========================================" << endl;
    cout << 't' << "FIRST集合" << "     " << "FOLLOW集合" << endl;
    for (it = VN.begin(); it != VN.end(); it++) {

        VN_First[count].VN_name = *it;
        VN_First[count].FIRST = get_FIRST(*it);

        mark_Follow[*it] = 0;
        VN_First[count].FOLLOW = get_FOLLOW(*it);

//-----------输出FIRST--------------------

        cout << VN_First[count].VN_name << 't';
        set<string>::iterator it;
        for (it = VN_First[count].FIRST.begin(); it != VN_First[count].FIRST.end(); it++) {
            cout << *it << "";
        }
        cout << 't' << "       ";
//----------------------------------------




//------------输出FOLLOW--------------
        set<string>::iterator it1;
        for (it1 = VN_First[count].FOLLOW.begin(); it1 != VN_First[count].FOLLOW.end(); it1++) {
            cout << *it1 << " ";
        }
        cout << endl;

//----------------------

        count++;
    }
    cout << "=========================================";
    cout << endl << endl;
}


void input() {
//创建一个文件输入流对象
    ifstream inFile;
//打开文件

    inFile.open("test.txt");
    if (inFile) { //条件成立,则说明文件打开成功
        cout << "FILE open scessful" << endl;
    } else
        cout << "file doesn't exist" << endl;

    string temp;
    getline(inFile, temp);
    for (int j = 0; j < temp.length(); j++) {
        VT.insert(temp.substr(j, 1));
    }
    set<string>::iterator p;
    cout << "终结符号:";
    for (p = VT.begin(); p != VT.end(); p++) {
        cout << *p << ",";
    }
    cout << endl;

    int count = 0;//文件行数
    while (getline(inFile, temp)) //按行读取文件内容
    {
        css[count].start = temp[0];
        for (int j = 3; j < temp.length(); j++) {
            css[count].next.push_back(temp.substr(j, 1));
        }
        VN.insert(css[count].start);//非终结符

        cout << css[count].start << "->";
        vector<string>::iterator it;
        for (it = css[count].next.begin(); it != css[count].next.end(); it++) {
            cout << *it;
        }
        cout << endl;


        count++;
    }
    CSSCount = count;


}

bool find_in_vector(vector<CSS_LR1> T, CSS_LR1 p) {
    vector<CSS_LR1>::iterator it;
    for (it = T.begin(); it != T.end(); it++) {
        if (*it == p) {
            return true;
        }
    }
    return false;
}


vector<CSS_LR1> CLOSURE(CSS_LR1 I) {//求闭包
    vector<CSS_LR1> T;
//T.push_back(I);
    if (I.num >= I.next.size()) { //规约项目A->α.或者接受项目
        return T;
    } else {
        string temp = I.next[I.num];
        if (VT.find(temp) != VT.end()) {     //点后面的是终结符 ,移进项目 A→α.aβ
            return T;
        } else {  //待约项目
            for (int i = 0; i < CSSCount; i++) {
                if (css[i].start == temp) {
                    CSS_LR1 p;
                    p.start = css[i].start;
                    p.num = 0;//点在最前面
                    p.next = css[i].next;

                    set<string> f1;
                    for (int j = I.num + 1; j < I.next.size(); j++) {
                        set<string> f2;//用于暂存first

                        if (VT.find(I.next[j]) != VT.end()) {

                            f2.insert(I.next[j]);
                        } else {
                            f2 = get_FIRST(I.next[j]);
                        }

                        f1.insert(f2.begin(), f2.end());
                        if (f2.find("$") == f2.end()) {

                            break;
                        }
                    }

                    if (f1.size() == 0) {
                        p.tail = I.tail;
                    } else {
                        vector<string> first_tail;
                        if (f1.find("$") != f1.end()) {
                            f1.erase("$");
                            copy(f1.begin(), f1.end(), back_inserter(first_tail));
                            first_tail.insert(first_tail.end(), I.tail.begin(), I.tail.end());
                        } else {
                            copy(f1.begin(), f1.end(), back_inserter(first_tail));
//cout<<first_tail[0]<<endl;
                        }
//                        vector<string>::iterator l;
//                        for(l=first_tail.begin();l!=first_tail.end();l++){
//                            cout<<*l<<" ";
//                        }cout<<endl;
                        p.tail = first_tail;
                    }
                    if (!find_in_vector(T, p)) {

                        T.push_back(p);
                        vector<CSS_LR1> ol = CLOSURE(p);
                        vector<CSS_LR1>::iterator z;
                        for (z = ol.begin(); z != ol.end(); z++) {
                            if (find_in_vector(T, *z)) {
                            } else {
                                T.push_back(*z);
                            }
                        }

                    }

                }
            }
        }
    }

    return T;
}

void showI(vector<CSS_LR1> I) {//展示项目集
    vector<CSS_LR1>::iterator it;
    for (it = I.begin(); it != I.end(); it++) {
        CSS_LR1 p = *it;
        cout << p.start << "->";
        vector<string>::iterator s;
        for (int j = 0; j < p.next.size(); j++) {
            if (j == p.num) cout << ".";
            cout << p.next[j];
        }
        if (p.num == p.next.size())cout << ".";
        cout << ",";
        for (int k = 0; k < p.tail.size(); k++) {
            cout << p.tail[k];
        }
        cout << endl;
    }
}

void LR1_Analyse() {
    CSS_LR1 p;
//初始项目 S’->.S ,#
    p.start = css[0].start + "^";
    p.num = 0;//点在最前面
    p.tail.push_back("#");
    p.next.push_back(css[0].start);

    I[0] = CLOSURE(p);//求闭包后的I[0]
    I[0].insert(I[0].begin(), p);///求闭包遇到了一些问题
    I_count = 1;

//计算项目集
    for (int i = 0; i < I_count; i++) {//每个项目集  项目集I(i)

        cout << "===================" << endl;
        cout << "现在在计算项目集I" << i << endl;
        showI(I[i]);//展示项目集
        cout << "===================" << endl;

//---------求ACTION的r部分--------------
        vector<CSS_LR1>::iterator t;
        for (t = I[i].begin(); t != I[i].end(); t++) {
            CSS_LR1 t2 = *t;
            if (t2.num == t2.next.size()) {
                int num = 0;
                for (int xp = 0; xp < CSSCount; xp++) {
                    if (css[xp].start == t2.start && css[xp].next == t2.next) {
                        num = xp;
                        break;
                    }
                }

                std::stringstream ss;
                ss << num;
                string s = ss.str();
                for (int q = 0; q < t2.tail.size(); q++) {
                    ACTION[i][t2.tail[q]] = "r" + s;
                }
                if (t2.num == 1 && t2.next[0] == css[0].start) {
                    ACTION[i]["#"] = "acc";
                }
            }
        }
//--------------------------------------



        set<string>::iterator it;
        for (it = VN.begin(); it != VN.end(); it++) {  //每个非终结符
//cout<<"项目集I"<<i<<"输入"<<*it<<endl;
            vector<CSS_LR1> temp;
//cout<<"项目集大小"<<I[i].size()<<endl;
            for (int j = 0; j < I[i].size(); j++) {
                CSS_LR1 lr = I[i][j];
                if (lr.num < lr.next.size() && lr.next[lr.num] == *it) {
//cout<<*it<<endl;
                    vector<CSS_LR1> t2;
                    lr.num++;
                    t2 = CLOSURE(lr);
                    t2.push_back(lr);

                    temp = temp + t2;
                }
            }
//cout<<"temp.size"<< temp.size()<<endl;

            if (temp.size() > 0) {
                int k;
                for (k = 0; k < I_count; k++) {//找一找项目集是否已经存在
                    if (cmp_vector(I[k], temp)) {
                        break;
                    }
                }
                if (k == I_count) {
//产生了新的项目集
                    I[I_count] = temp;
/*
cout<<"---------------------"<<endl;
cout<<"新的项目集I"<<I_count<<endl;
cout<<"  I"<<i<<" -- "<<*it<<"->"<<"I"<<I_count<<endl<<endl;
showI(I[I_count]);//展示项目集
cout<<"---------------------"<<endl;
*/
                    cout << "  I" << i << " -- " << *it << "->" << "I" << I_count << endl << endl;
                    GOTO[i][*it] = I_count;//更新goto表
                    I_count++;
                } else {
//项目集已经存在,需要自己指向自己
                    cout << "  I" << i << " -- " << *it << "->" << "I" << k << endl << endl;
                    GOTO[i][*it] = k;

                }

            }

        }
        for (it = VT.begin(); it != VT.end(); it++) {  //每个终结符
//cout<<"项目集I"<<i<<"输入"<<*it<<endl;
            vector<CSS_LR1> temp;

            for (int j = 0; j < I[i].size(); j++) {
                CSS_LR1 lr = I[i][j];

                if (lr.num < lr.next.size() && lr.next[lr.num] == *it) {
                    vector<CSS_LR1> t2;
                    lr.num++;
                    t2 = CLOSURE(lr);//闭包求出的结果不包含本身
                    t2.insert(t2.begin(), lr);/求闭包遇到了一些问题
//showI(t2);
                    temp = temp + t2;
                }
            }
//cout<<"temp.size"<< temp.size()<<endl;
            if (temp.size() > 0) {
                int k;
                for (k = 0; k < I_count; k++) {//找一找项目集是否已经存在
                    if (cmp_vector(I[k], temp)) {
                        break;
                    }
                }
                if (k == I_count) {
//产生了新的项目集
                    I[I_count] = temp;
/*
cout<<"---------------------"<<endl;
cout<<"新的项目集I"<<I_count<<endl;
cout<<"  I"<<i<<" -- "<<*it<<"->"<<"I"<<I_count<<endl<<endl;
showI(I[I_count]);//展示项目集
cout<<"---------------------"<<endl;
*/
                    cout << "  I" << i << " -- " << *it << "->" << "I" << I_count << endl << endl;
                    std::stringstream ss;
                    ss << I_count;
                    string s = ss.str();
                    ACTION[i][*it] = "S" + s;//更新AVTION表
                    I_count++;
                } else {
//项目集已经存在,需要自己指向自己
                    cout << "  I" << i << " -- " << *it << "->" << "I" << k << endl << endl;
                    std::stringstream ss;
                    ss << k;
                    string s = ss.str();
                    ACTION[i][*it] = "S" + s;

                }

            }
        }


    }


}

void print_line() {
    cout << "-----------------------------------------------------------------------------" << endl;
}


void print_ACTION_GOTO() {
    set<string>::iterator it;
    print_line();
    cout << setw(27) << setiosflags(ios::right) << "ACTION";
    cout << setw(20) << setiosflags(ios::left) << "  GOTO" << endl;
    print_line();
    cout << setw(8) << "项目集" << "|";

    for (it = VT.begin(); it != VT.end(); it++) {
        cout << setw(8) << *it << "|";
    }
    cout << setw(8) << "#" << "|";
    for (it = VN.begin(); it != VN.end(); it++) {
        cout << setw(8) << *it << "|";
    }
    cout << endl;
    for (int j = 0; j < I_count; j++) {
        cout << setw(6) << "I" << setw(2) << j << "|";
        for (it = VT.begin(); it != VT.end(); it++) {
            cout << setw(8) << ACTION[j][*it] << "|";
        }
        cout << setw(8) << ACTION[j]["#"] << "|";
        for (it = VN.begin(); it != VN.end(); it++) {

            if (GOTO[j][*it])//GOTO表为0
                cout << setw(8) << GOTO[j][*it] << "|";
            else {
                cout << setw(8) << " " << "|";
            }
        }
        cout << endl;
    }
    print_line();

}


//对栈容器进行输出,i=0,返回status中的字符串,i=1,返回sign中的字符串,i=2返回inputStr中的字符串
string vectTrancStr(int i, vector<int> status, vector<string> sign) {
    string buf;
    int count = 0;
//输出状态栈
    if (i == 0) {
        vector<int>::iterator it = status.begin();
//将数字转化为字符串
        string str, tempStr;
        for (it; it != status.end(); it++) {
            stringstream ss;
            ss << *it;
            ss >> tempStr;
            str += tempStr;
        }
        return str;
    }
//输出符号栈
    else if (i == 1) {
        vector<string>::iterator it = sign.begin();
        for (it; it != sign.end(); it++) {
            buf += *it;
            count++;
        }
    }


    string str(buf);
    return str;
}


void Input_Analyse() {//输入句子,开始分析

    vector<int> status;//定义状态栈
    vector<string> sign;//定义符号栈

    int step = 1;  //步骤
    string input;
    cout << "请输入分析的字符串(请以#结尾):";
    cin >> input;//输入待分析的句子
    input = input + "#";

    status.push_back(0);//把状态0入栈
//把#加入符号栈
    sign.push_back("#");
//输出初始栈状态
    cout << setw(10) << "步骤" << setw(10) << "状态栈" << setw(10) << "符号栈" << setw(10) << "输入串" << setw(25) << "动作说明"
         << endl;

    int s = 0;//初始状态

    int oldStatus;//保存之前的状态


    string input_s;  //获取初始符号
    input_s = input.substr(0, 1);

    while (ACTION[s][input_s] != "acc") {//如果action[s][input_s] =="acc" ,则分析成功
//获取字符串
        string str = ACTION[s][input_s];
//如果str为空,报错并返回
        if (str.size() == 0) {
            cout << "出错";
            return;
        }
//获取S或r后面的数字
        stringstream ss;
        ss << str.substr(1);
        ss >> s;//新的状态号
//如果是移进
        if (str.substr(0, 1) == "S") {
            cout << setw(10) << step << setw(10) << vectTrancStr(0, status, sign) << setw(10)
                 << vectTrancStr(1, status, sign) << setw(10) << input << setw(10) << "A" << "CTION[" << status.back()
                 << "," << input_s << "]=S" << s << "," << "状态" << s << "入栈" << endl;
            sign.push_back(input_s); //输入符号入栈
            input.erase(0, 1);
            status.push_back(s);//将状态数字入栈
        }
//如果是规约
        else if (str.substr(0, 1) == "r") {
            string kaitou;//产生式的头部
            kaitou = css[s].start;
            int pop_num = css[s].next.size();//获取符号栈的出栈次数

            string r;
            stringstream ss;
            ss << s;
            ss >> r;
            int oldStatus;//保存之前的状态
            int status_size = status.size();
            oldStatus = status[status_size - 1 - pop_num];
            s = GOTO[oldStatus][kaitou];
            cout << setw(10) << step << setw(10) << vectTrancStr(0, status, sign) << setw(10)
                 << vectTrancStr(1, status, sign) << setw(10) << input << setw(10)
                 << (string) ":产生式" + r + (string) "归约,GOTO(" << oldStatus << "," << kaitou << ")=" << s << "入栈"
                 << endl;
//对符号栈进行出栈和状态栈进行出栈
            while (pop_num--) {
                sign.pop_back();
                status.pop_back();
            }

            sign.push_back(kaitou);//再对产生式的开始符号入栈
            status.push_back(s);//再把新的状态入栈
        } else {
//nothing
        }

        step++; //步骤数加1

        s = status.back();//获取栈顶状态

        input_s = input.substr(0, 1);//获取输入的字符
    }
    cout << setw(10) << step << setw(10) << vectTrancStr(0, status, sign) << setw(10) << vectTrancStr(1, status, sign)
         << setw(10) << input << setw(10) << "A" << "cc:分析成功" << endl;


}

int main() {
    input();//输入二型文法
    GetFirst_and_Follow();//求First和Follow集合
    LR1_Analyse();
    print_ACTION_GOTO();//打印ACTION GOTO表
    Input_Analyse();//输入句子,开始分析
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LR语法分析器编译原理中的一种语法分析方法,它可以根据给定的文法规则,对输入的程序代码进行分析和解析。LR语法分析器使用自底向上的分析方法,通过构建一个状态机来识别输入的符号串是否符合给定的文法规则。 LR语法分析器的实现通常使用工具,如Bison(Yacc的GNU版本),它可以根据给定的文法规则自动生成相应的语法分析器LR语法分析器的工作原理如下: 1. 构建LR分析表:根据给定的文法规则,LR语法分析器会构建一个分析表,该表记录了在不同状态下,对应不同输入符号的移进、规约或接受操作。 2. 状态转移:LR语法分析器通过状态转移来处理输入符号串。它从初始状态开始,根据当前状态和下一个输入符号,查找分析表中对应的操作,并执行相应的移进或规约操作。 3. 移进操作:当遇到终结符号时,LR语法分析器会将该符号移入栈中,并读取下一个输入符号。 4. 规约操作:当遇到非终结符号时,LR语法分析器会根据文法规则进行规约操作,将栈中的符号按照规约规则进行替换。 5. 接受操作:当输入符号串被完全分析并符合文法规则时,LR语法分析器会执行接受操作,表示输入符号串被成功地分析和解析。 通过使用LR语法分析器,可以对程序代码进行语法分析,并生成相应的抽象语法树(AST)。抽象语法树可以用于后续的语义分析和代码生成等编译过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值