喵哖哖 2017-11-07 11:58 采纳率: 0%
浏览 2632

使用C/C++编程实现消除左递归

老菜鸟……请各路大神不小心翻到牌的时候抽空教一哈,
个人思路是先判断文法式子是否可推导,定义一维数组存放被|分开的字符串,但是写不出来,求源代码QAQ

  • 写回答

1条回答 默认 最新

  • fcyh 2017-11-07 12:01
    关注
     #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <queue>
    #include <cctype>
    #include <map>
    #include <set>
    #define MAX 507
    
    using namespace std;
    
    class WF
    {
        public:
            string left;
            set<string> right;
            WF ( const string& temp )
            {
                left = temp;
                right.clear();
            }
            void print ( )
            {
                printf ( "%s::=" , left.c_str() );
                set<string>::iterator it = right.begin();
                printf ( "%s" , it->c_str());
                it++;
                for ( ; it!= right.end() ; it++ )
                    printf ( "|%s" , it->c_str() );
                puts("");
            }
            void insert ( const string& temp )
            {
                right.insert(temp);
            }
    };
    
    map<string,int> VN_dic;
    vector<WF> VN_set;
    string start;
    bool used[MAX];
    
    //消除间接左递归
    void remove1 ( )
    {
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            for ( int j = 0 ; j < i ; j++ )
            {
                vector<string> cont;
                set<string>& right1 = VN_set[i].right;
                set<string>& right2 = VN_set[j].right;
                char ch = VN_set[j].left[0];
                set<string>::iterator it1 = right1.begin();
                set<string>::iterator it2;
                for ( ; it1 != right1.end() ; it1++ )
                    if ( it1->at(0) == ch )
                        for ( it2 = right2.begin() ; it2 != right2.end() ; it2++ )
                            cont.push_back ( *it2 + it1->substr(1) ); 
                int nn = right1.size();
                while ( nn-- )
                {
                    if ( right1.begin()->at(0) == ch ) 
                        right1.erase ( right1.begin() );
                    else 
                    {
                        cont.push_back ( *right1.begin() );
                        right1.erase ( right1.begin() );
                    }
                }
                for ( int i = 0 ; i < cont.size() ; i++ )
                    right1.insert ( cont[i] );
            }
    #define DEBUG
    #ifdef DEBUG
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            VN_set[i].print();
    #endif
    }
    
    //消除直接左递归
    void remove2 ( )
    {
        for ( int i = 0 ; i < VN_set.size() ; i++ )
        {
            char ch = VN_set[i].left[0];
            set<string>& temp = VN_set[i].right;
            set<string>::iterator it = temp.begin();
            string tt = VN_set[i].left.substr(0,1)+"\'";
            bool flag = true;
            for ( ; it != temp.end() ; it++ )
                if ( it->at(0) == ch )
                {
                    VN_set.push_back ( WF(tt));
                    VN_dic[tt] = VN_set.size();
                    flag = false;
                    break;
                }
            int x = VN_dic[tt]-1;
            if ( flag ) continue;
            vector<string> cont;
            set<string>& ss = VN_set[x].right;
            ss.insert ( "~" );
            while (!temp.empty())
            {
                if ( temp.begin()->at(0) == ch )
                    ss.insert(temp.begin()->substr(1)+tt);
                else 
                {
                    //cout << "YES : " << temp.begin()->substr(1)+tt;
                    cont.push_back (temp.begin()->substr(0)+tt);
                }
                temp.erase(temp.begin());
            }
            puts ("");
            for ( int i = 0 ; i < cont.size() ; i++ )
            {
                //cout << cont[i] << endl;
                temp.insert ( cont[i] );
            }
        }
    #define DEBUG
    #ifdef DEBUG
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            VN_set[i].print();
    #endif
    }
    
    void dfs ( int x )
    {
        if ( used[x] ) return;
        used[x] = 1;
        set<string>::iterator it = VN_set[x].right.begin();
        for ( ; it != VN_set[x].right.end(); it++ )
            for ( int i = 0 ; i < it->length() ; i++ )
                if ( isupper(it->at(i)) )
                {
                    if ( it->length() > i+1 && it->at(i+1) == '\'' )
                        dfs ( VN_dic[it->substr(i,2)]-1 );
                    else 
                        dfs ( VN_dic[it->substr(i,1)]-1 );
                }
    }
    
    //化简
    void simplify ( )
    {
        memset ( used , 0 , sizeof ( used ) );
        int x = VN_dic[start]-1;
        dfs ( x );
        puts ( "finish" );
        vector<WF> res;
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            if ( used[i] ) 
                res.push_back ( VN_set[i] );
        VN_set.clear();
        VN_set = res;
    }
    
    void  print () 
    {
        puts("**********消除左递归后的结果********");
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            VN_set[i].print();
        puts("");
    }
    
    int main ( )
    {
        char buf[MAX];
        int n;
        VN_dic.clear();
        VN_set.clear();
        start="S";
        puts ("请输入文法G[S]的产生式数量");
        while ( ~scanf ("%d" , &n ) )
        {
            scanf ( "%d" , &n );
            while ( n-- )
            {
                scanf ( "%s" , buf );
                int len = strlen ( buf ),i;
                for ( i = 0 ; i < len ; i++ )
                    if ( buf[i] == ':' ) 
                    {
                        buf[i] = 0;
                        break;
                    }
                string temp = buf;
                if ( !VN_dic[temp] )
                {
                    VN_set.push_back ( WF(temp));
                    VN_dic[temp] = VN_set.size();
                }
                int x = VN_dic[temp]-1;
                temp = buf+i+3;
                //cout <<"the right :  " << temp << endl;
                VN_set[x].insert(temp);
            }
            remove1();
            remove2();
            simplify();
            print();
            //puts ("请输入文法G[S]的产生式数量");
        }   
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建