LR 语法分析器的设计与实现

一、实验目的

        理解 LR 语法分析方法的原理,设计相关数据结构和程序结构, 加深对自下而上语法分析方法的理解。

二、问题描述

需要实现的功能:

(1)输入文法:文法描述存储在文本文件中,文件名作为命令行 参数输入;

(2)输入文法的分析表(Action 表和 Goto 表):分析表数据存储 在文本文件中,文件名作为命令行参数输入;

(3)输入待分析的符号串:符号串存储在文本文件中,文件名 作为命令行参数输入。

(4)构造 LR 语法分析器的总控程序;

(5)对待分析符号串,输出其是否该文法正确句子的判断,并 输出文本形式的分析过程(标准输出设备)。

实现原理:

LR 方法的基本思想: 在归约过程中 记住“历史”:记住已移进和归约出的整个符号串; 展望“未来”:根据使用的规则预测未来可能遇到的输入符号 。根据记住的“历史”、展望的“未来”和“现实”的输入符号 三方面材料,来确定现在的栈顶符号串是否已经形成相对于某 个规则的句柄。

三、软件设计方法的选择

1、选用面向对象的软件设计方法;

2、开发语言:C++;

3、语言标准(-std):ISO C++11

4、编译器:g++;

5、开发环境:clion 集成开发环境

四、测试数据与测试效果

将如下字符输入到一个txt文件里,程序以文件方式读取

 五、代码

#include "iostream"
#include <vector>
#include <fstream>
#include <sstream>
#include <map>
#include <stack>
#include "string"
#include "set"
using namespace std;
#ifndef BIANYI_LRALL_H
#define BIANYI_LRALL_H

class VN{   //非终结符集
private:
    int n;
    set<string> vn;
public:
    int getN() const {
        return n;
    }

    const set<string> &getVn() const {
        return vn;
    }

    void setVn(const set<string> &vn) {
        VN::vn = vn;
    }

    void setN(int n) {
        VN::n = n;
    }

};

class VT{   //终结符集
private:
    int n;
    set<string> vt;
public:
    int getN() const {
        return n;
    }

    void setN(int n) {
        VT::n = n;
    }

    const set<string> &getVt() const {
        return vt;
    }

    void setVt(const set<string> &vt) {
        VT::vt = vt;
    }
};

class P{    //产生式
private:
    int n;
    vector<string> p1;  //存放左部
    vector<vector<string>> p2;  //存放右部
public:
    const vector<vector<string>> &getP2() const {
        return p2;
    }

    void setP2(const vector<vector<string>> &p2) {
        P::p2 = p2;
    }

    const vector<string> &getP1() const {
        return p1;
    }

    void setP1(const vector<string> &p1) {
        P::p1 = p1;
    }

    int getN() const {
        return n;
    }

    void setN(int n) {
        P::n = n;
    }

};

class S{    //开始符号
private:
    string s;
public:
    const string &getS() const {
        return s;
    }

    void setS(const string &s) {
        S::s = s;
    }
};
class CFG{
public:
    string filewenfa;   //文法文件
    VN vn;
    VT vt;
    P p;
    S s;

public:
    void setFilewenfa(const string &filewenfa) {
        CFG::filewenfa = filewenfa;
    }
    void fileop() {     //读文件
        string fileline;
        string str;
        set<string> middle;
        vector<string> p1;
        vector<string> mid;
        vector<vector<string>> p2;
        ifstream fout(filewenfa);
        for (int i = 1; getline(fout, fileline); i++) {
            if (i == 1) {
                vn.setN(atoi(fileline.c_str()));//非终结符个数
            } else if (i == 2) {  //非终结符集合
                istringstream is(fileline);
                while (is >> str) {
                    middle.insert(str);
                }
                vn.setVn(middle);
                middle.clear();
            } else if (i == 3) {  //终结符个数
                vt.setN(atoi(fileline.c_str()));
            } else if (i == 4) {  //终结符集合
                istringstream is(fileline);
                while (is >> str) {
                    middle.insert(str);
                }
                vt.setVt(middle);
                middle.clear();
            } else if (i == 5) {  //规则个数
                p.setN(atoi(fileline.c_str()));
            } else if (i == p.getN() + 6) { //指定开始符
                s.setS(fileline.c_str());
            } else {
                istringstream is(fileline);
                for (int j = 0; is >> str; j++) {
                    if (j == 0) {
                        p1.push_back(str);
                    } else if (j == 1);
                    else {
                        mid.push_back(str);
                    }
                }
                p2.push_back(mid);
                mid.clear();
            }
        }
        fout.close();
        p.setP1(p1);
        p.setP2(p2);
    }
};

class Program{
private:
    string filewenfa;   //文法文件
    string fileAG;      //Actiongto表
    string filestr;     //待分析串
    CFG cfg;
    vector<string> anstr;   //储存待分析串
    map<pair<int,int>,string> action;   //action表
    map<pair<int,int>,int> Goto;    //goto表
    map<string,int> X;  //终结符编号
    map<string,int> Y;  //非终结符编号
public:
    void setFileAg(const string &fileAg) {
        fileAG = fileAg;
    }

    void setFilestr(const string &filestr) {
        Program::filestr = filestr;
    }

    void setFilewenfa(const string &filewenfa) {
        Program::filewenfa = filewenfa;
    }
    void fileAGop(){    //读分析表
        int num;
        string str;
        pair<int,int> midp;
        ifstream fout(this->fileAG);
        string fileline;
        for (int i = 1; getline(fout, fileline); i++) {
            if (i == 1) {
                num=atoi(fileline.c_str());
                continue;
            } else if(i!=1&&i<=num+1){
                istringstream is(fileline);
                is>>str;
                midp.first=atoi(str.c_str());
                str.clear();
                is>>str;
                midp.second=atoi(str.c_str());
                str.clear();
                is>>str;
                this->action.emplace(midp,str);
                str.clear();
            } else if(i==num+2){

            } else{
                istringstream is(fileline);
                is>>str;
                midp.first=atoi(str.c_str());
                str.clear();
                is>>str;
                midp.second=atoi(str.c_str());
                str.clear();
                is>>str;
                this->Goto.emplace(midp,atoi(str.c_str()));
                str.clear();
            }
        }
        fout.close();
    }
    void filestrop(){   //读待分析串
        ifstream fout(this->filestr);
        stringstream buffer;
        buffer<<fout.rdbuf();
        fout.close();
        string ss;
        string contents(buffer.str());//将文件读入一个字符串
        istringstream is(contents);
        while (is >> ss) {
            this->anstr.push_back(ss);
        }
    }
    void initstr(){ //按分析表给非终结符和终结符编号
        int i=0;
        for(set<string>::iterator it=cfg.vt.getVt().begin();it!=cfg.vt.getVt().end();it++){
            this->X.emplace(*it,i);
            i++;
        }
        this->X.emplace("#",i);
        i=0;
        for(set<string>::iterator it=cfg.vn.getVn().begin();it!=cfg.vn.getVn().end();it++){
            if(*it!=cfg.s.getS())this->Y.emplace(*it,i);
            i++;
        }
    }
    void fileop(){  //调用所有读文件操作
        this->cfg.setFilewenfa(filewenfa);
        this->cfg.fileop();
        this->filestrop();
        this->fileAGop();
        initstr();
    }
    void allprogram(){
        string sstr;    //  中间字符串
        string a;   //待入栈符号
        stack<int> state;  //状态栈
        stack<string> str;  //符号栈
        state.push(0);  //初始状态入栈
        str.push("#");  //结束符入符号栈
        int k=1;
        pair<int,int> midp; //中间pair
        midp.first=state.top();
        a=anstr[0];
        midp.second= X[a];
        cout<<"栈顶    "<<"输入    "<<"查表    "<<"动作    "<<endl;
        while (action[midp]!="acc"){
            cout<<state.top()<<" "<<str.top()<<"     "<<a<<"      ";
            if(action[midp][0]=='s'){ //移进
                sstr=action[midp];
                sstr.erase(0,1);
                state.push(atoi(sstr.c_str()));
                cout<<action[midp]<<"     "<<"进栈"<<" "<<atoi(sstr.c_str())<<" "<<a<<endl;
                sstr.clear();
                str.push(a);
                a=anstr[k];
                k++;
            } else if(action[midp][0]=='r'){    //归约
                sstr=action[midp];
                sstr.erase(0,1);
                int n=atoi(sstr.c_str());   //按照第n条规则归约
                for(int i=0;i<cfg.p.getP2()[n].size();i++){ //n个状态和符号出栈
                    state.pop();
                    str.pop();
                }
                str.push(cfg.p.getP1()[n]); //归约的非终结符入栈
                cout<<action[midp]<<"     "<<"出栈"<<cfg.p.getP2()[n].size()<<"个符号和状态";
                midp.first=state.top();
                midp.second=Y[cfg.p.getP1()[n]];
                if(Goto.count(midp)==1){    //查goto表状态转移
                    state.push(Goto[midp]);
                }
                cout<<"进栈"<<state.top()<<" "<<str.top()<<" ";
                cout<<cfg.p.getP1()[n]<<"->";
                for(int i=0;i<cfg.p.getP2()[n].size();i++){
                    cout<<cfg.p.getP2()[n][i];
                }
                cout<<endl;

            } else{ //出错处理
                cout<<"error!"<<endl;
                break;
            }
            midp.first=state.top();
            midp.second=X[a];
            if(action[midp]=="acc"){
                cout<<state.top()<<" "<<str.top()<<"    "<<a<<"       "<<action[midp]<<"    "<<"成功接受!";
            }
        }
    }
};

#endif //BIANYI_LRALL_H

int main(){
    string filewenfa;
    string fileAG;
    string filestr;
    cout<<"Please input file(absolute path; eg: D://filename.txt):"<<endl;  
    cin>>filewenfa;
    cout<<"Please input file(absolute path; eg: D://filename.txt):"<<endl;  
    cin>>fileAG;
    cout<<"Please input file(absolute path; eg: D://filename.txt):"<<endl;  
    cin>>filestr;
    Program program;
    program.setFilewenfa(filewenfa);
    program.setFileAg(fileAG);
    program.setFilestr(filestr);
    program.fileop();   //读文件
    program.allprogram();   //总控分析
    return 0;
}

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值