文法构造二

一、实验目的

        在实验《文法构造一》的基础上,改进文法数据结构的设计,实现First集、Follow集和Select集的计算,进一步加深对文法的理解。

二、实验内容

需要实现的功能:

1)实现First集、Follow集和Select集的计算;

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

3)输出每个非终结符的First集到标准输出设备;

4)输出每个非终结符的Follow集到标准输出设备;

5)输出每个产生式的Select集到标准输出设备;

附件:样例

描述:

算术表达式文法G =(VN,VT,P,S)其中:

   VN = { S, T, T’ }

   VT = { a, ^, (, ) ,}

   P = { S → a | ^ |(T)

   T → ST’

   T’ → ,ST’ | e }

   S = S

输入(文法描述文件):

3

S T T'

5

a ^ ( ) ,

6

S -> a

S -> ^

S -> ( T )

T -> S T'

T' -> , S T'

T' -> ε

S

输出(标准输出设备):

CFG=(VN,VT,P,S)

  VN: S T T'

  VT: a ^ ( ) ,

  Production:

     0: S -> a

     1: S -> ^

     2: S -> ( T )

     3: T -> S T'

     4: T' -> , S T'

     5: T' -> ε

  StartSymbol: S

[First Set]

  S               : ^  (  a 

  T               : ^  (  a 

  T'              : ε  , 

[Follow Set]

  S               : #  ,  ) 

  T               : ) 

  T'              : ) 

[Select Set]

   0:S -> a                         : a 

   1:S -> ^                         : ^ 

   2:S -> ( T )                     : ( 

   3:T -> S T'                      : ^  (  a 

   4:T' -> , S T'                   : , 

   5:T' -> ε                       : ) 

三、代码

#include <fstream>
#include <sstream>
#include "iostream"
#include "set"
#include "string"
#include "map"
#include "vector"
using namespace std;
#ifndef BIANYI_WENFA_H
#define BIANYI_WENFA_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{
private:
    string filename;
    VN vn;
    VT vt;
    P p;
    S s;
public:
    void setFilename(const string &filename) {
        CFG::filename = filename;
    }

    void fileop() {     //读文件
        string fileline;
        string str;
        set<string> middle;
        vector<string> p1;
        vector<string> mid;
        vector<vector<string>> p2;
        ifstream fout(filename);
        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();
            }
        }
        p.setP1(p1);
        p.setP2(p2);
    }

    void output(){  //输出CFG
        cout<<"CFG=(VN,VT,P,S)"<<endl;
        cout<<"VN: ";
        for(set<string>::iterator it=vn.getVn().begin();it!=vn.getVn().end();it++){
            cout<<*it<<" ";
        }
        cout<<endl<<"VT: ";
        for(set<string>::iterator it=vt.getVt().begin();it!=vt.getVt().end();it++){
            cout<<*it<<" ";
        }
        cout<<endl<<"Production:"<<endl;
        for(int i=0;i<p.getP1().size();i++){
            cout<<"     "<<i<<":"<<p.getP1()[i]<<" -> ";
            for(int j=0;j<p.getP2()[i].size();j++){
                cout<<p.getP2()[i][j];
            }
            cout<<endl;
        }
        cout<<"StartSymbol: ";
        cout<<s.getS()<<endl;
    }
    set<string> First1(string str){ //求单个非终结符First集
        set<string> first;
        set<string> second; //中间集合
        if(vt.getVt().count(str)==1){   //终结符本身即为其First集
            first.insert(str);
            return first;
        }
        for(int i=0;i<p.getP1().size();i++){
            if(str==p.getP1()[i]){  //在左部集找到该非终结符
                if(vt.getVt().count(p.getP2()[i][0])==1 || p.getP2()[i][0]=="ε"){   //如果产生式右部第一个字符为终结符或ε,则直接加入其First集
                    first.insert(p.getP2()[i][0]);
                }
                else if(vn.getVn().count(p.getP2()[i][0])==1){  //右部第一个为非终结符
                    for(int j=0;j<p.getP2()[i].size();j++){ //产生式右部遍历
                        if(vt.getVt().count(p.getP2()[i][j])==1){   //如果是终结符,加入first集,结束遍历
                            first.insert(p.getP2()[i][j]);
                            break;
                        }else if(vn.getVn().count(p.getP2()[i][j])==1 && j!=p.getP2()[i].size()-1){ //如果是非终结符
                            second =First1(p.getP2()[i][j]);    //递归调用
                            if(second.count("ε")==0){
                                first.insert(second.begin(),second.end());
                                second.clear();
                                break;
                            }
                            else{
                                second.erase("ε");
                                first.insert(second.begin(),second.end());
                                second.clear();
                            }
                        } else if(vn.getVn().count(p.getP2()[i][j])==1 && j==p.getP2()[i].size()-1){
                            second =First1(p.getP2()[i][j]);
                            first.insert(second.begin(),second.end());
                            second.clear();
                        }
                    }
                }
            }
        }
        return first;
    }

    void First(){   //求每一个非终结符First集
        map<string,set<string>> first;
        for(set<string>::iterator it=vn.getVn().begin();it!=vn.getVn().end();it++){
            first.emplace(*it, First1(*it));
        }
        cout<<"[First Set]"<<endl;  //输出First集
        for(map<string,set<string>>::iterator it=first.begin();it!=first.end();it++){
            cout<<it->first<<"  :";
            for(set<string>::iterator jj=it->second.begin();jj!=it->second.end();jj++){
                cout<<*jj<<" ";
            }
            cout<<endl;
        }
    }

    set<string> Follow1(string str) {   //求单个非终结符的Follow集
        set<string> follow;
        set<string> second;
        if (str == s.getS()) {
            follow.insert("#");     //若是开始符,则将#加入
        }
        for (int i = 0; i < p.getP2().size(); i++) {    //遍历产生式右部
            for (int j = 0; j < p.getP2()[i].size(); j++) {
                if (str == p.getP2()[i][j]) {
                    if (j == p.getP2()[i].size()-1) {   //若其后无元素,则将产生式左部follow集加入
                        if(p.getP1()[i]!=str){
                            second = Follow1(p.getP1()[i]); //递归调用
                            follow.insert(second.begin(), second.end());
                            second.clear();
                        }

                    }
                else{
                        if(vn.getVn().count(p.getP2()[i][j+1])==1){
                            for(int k=j+1;k<p.getP2()[i].size();k++){
                                second =First1(p.getP2()[i][k]);
                                if(second.count("ε")==0){
                                    follow.insert(second.begin(),second.end());
                                    second.clear();
                                    break;
                                } else {
                                    if(k==p.getP2()[i].size()-1){
                                        second.erase("ε");
                                        follow.insert(second.begin(),second.end());
                                        second.clear();
                                        if(p.getP1()[i]!=p.getP2()[i][k]){
                                            second = Follow1(p.getP1()[i]); //递归调用
                                            follow.insert(second.begin(), second.end());
                                            second.clear();
                                        }
                                    } else{
                                        second.erase("ε");
                                        follow.insert(second.begin(),second.end());
                                        second.clear();
                                    }

                                }
                            }
                        } else if(vt.getVt().count(p.getP2()[i][j+1])){
                            follow.insert(p.getP2()[i][j+1]);
                            break;
                        }
                }
               }
            }
        }
            return follow;
    }

    void Follow(){  //求所有非终结符的follow
        map<string,set<string>> follow;
        for(set<string>::iterator it=vn.getVn().begin();it!=vn.getVn().end();it++){
            follow.emplace(*it, Follow1(*it));
        }
        cout<<"[Follow Set]"<<endl;
        for(map<string,set<string>>::iterator it=follow.begin();it!=follow.end();it++){
            cout<<it->first<<"  : ";
            for(set<string>::iterator jj=it->second.begin();jj!=it->second.end();jj++){
                cout<<*jj<<" ";
            }
            cout<<endl;
        }
    }
    void Select(){  //Select集
        map<int,set<string>> select;
        set<string> second;
        set<string> sle;
        for(int i=0;i<p.getP2().size();i++){    //遍历产生式右部
            if(p.getP2()[i][0]=="ε"){   //若为空串,则将左部follow加入
                second= Follow1(p.getP1()[i]);
                sle.insert(second.begin(), second.end());
                second.clear();
                select.emplace(i,sle);
                sle.clear();
                continue;
            }
            for(int j=0;j<p.getP2()[i].size();j++){ //  计算产生式右部first集

                second=First1(p.getP2()[i][j]);
                if(second.count("ε")==0){
                    sle.insert(second.begin(),second.end());
                    second.clear();
                    break;
                } else{
                    if(j==p.getP2()[i].size()-1){
                        sle.insert(Follow1(p.getP1()[i]).begin(), Follow1(p.getP1()[i]).end());
                    }
                    second.erase("ε");
                    sle.insert(second.begin(),second.end());
                    second.clear();
                }
            }
            select.emplace(i,sle);
            sle.clear();
        }
        cout<<"[Select Set]"<<endl; //输出select集
        for(int i=0;i<p.getP1().size();i++){
            cout<<i<<" : "<<p.getP1()[i]<<"->";
            for(int k=0;k<p.getP2()[i].size();k++){
                cout<<p.getP2()[i][k]<<" ";
            }
            cout<<" : ";
            for(set<string>::iterator j=select[i].begin();j!=select[i].end();j++){
                cout<<*j<<" ";
            }
            cout<<endl;
        }
    }
};
#endif //BIANYI_WENFA_H
int main(){
    string filename;
    CFG cfg;
    cout<<"Please input file(absolute path; eg: D://filename.txt):"<<endl;  //E://by//exp5.txt
    cin>>filename;
    cfg.setFilename(filename);
    cfg.fileop();
    cfg.output();
    cfg.First();
    cfg.Follow();
    cfg.Select();
    return 0;
}

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值