【编译原理】LL(1)文法分析全过程(FIRST/FLLOW/SELECT集等)实现(c++语言)

  • Post author:
  • Post category:其他



注:本程序只能进行LL(1)文法的分析,非LL(1)文法请转化为LL(1)文法


变量声明


string M[2000][2000];     //任务分析表
stack <char> cc;          //分析栈
queue <char> qq;          //输入串
set <char> ww[200];       //first集
set <char> T;             //终结符集
set <char> N;             //非终结符集合
set <char> vv[200];       //中间过程记录集
set <char> ff[200];       //fllow集合
set <char> select[200];   //select集合

int step = 0;             //步骤统计变量
int error_flag=0;         //错误标志位
int nullflag[1000];       //是否推空标志
int nullselect[1000];     //集合是否推空标志
int ll=0;                 //文法行数
int T_flag[1000];         //右侧是否含有终结符
int length_char[1000];    //每行文法的字符个数
char line[100][1024];     //文法记录表




输入&初步分析:文件输入(每个文法一行,如A->B)


void raedFromFile()
{
    fstream infile("project.txt",ios::in);
    while(infile.getline(line[ll],sizeof(line[ll])))
    {
        for(int i=0;i<100;i++)
        {
            if(int(line[ll][i])==0)
                {
                    length_char[ll]=i;
                    break;
                }
            if(isT(line[ll][i]))
                T_flag[ll]=1;
                T.insert(line[ll][i]);
            if(isN(line[ll][i]))
                N.insert(line[ll][i]);
        }
        if(isT(line[ll][3]))
        {
            //first集合
            if(line[ll][3]=='^')
            {
                nullflag[int(line[ll][0])]=1;
            }
            ww[int(line[ll][0])].insert(line[ll][3]);
        }else
        {
            vv[int(line[ll][0])].insert(line[ll][3]);
        }
        ll++;
    }
}




求FIRST集

void firstSet()
{
    for(int i=0;i<ll;i++)
    {
        if(isN(line[i][3]))
        {
            int j=3;
            while(nullflag[int(line[i][j])]==1)
            {
                if(j+1==length_char[i])
                {
                    break;
                }
                if(isN(line[i][j+1]))
                {
                    vv[int(line[i][0])].insert(line[i][j+1]);
                    j++;
                }
            }
        }
    }
    while(!isEmpty())
    {
        for(set<char>::iterator ite1 = N.begin();ite1!=N.end();ite1++)
        {
            //对于所有非终结符
            //如果他的first已经完毕收集
            if(vv[int(*ite1)].empty())
            {
                //那么就把他的first加入到含有他的vv中
                for(set<char>::iterator ite3 = N.begin();ite3!=N.end();ite3++)
                {
                    for(set<char>::iterator ite4 = vv[int(*ite3)].begin();ite4!=vv[int(*ite3)].end();ite4++)
                    {
                        if(*ite4==*ite1)
                        {
                            vv[int(*ite3)].erase(*ite4);
                            //ite1的first集
                            for(set<char>::iterator ite5 = ww[int(*ite1)].begin();ite5!=ww[int(*ite1)].end();ite5++)
                            {
                              ww[int(*ite3)].insert(*ite5);
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}


FLLOW集

void fllowSet()
{
    ff[int(line[0][0])].insert('#');
    for(int i=0;i<ll;i++)
    {
        int j=3;
        while(j!=length_char[i])
        {
            //依次考虑每个非终结符,分情况,情况就是我们平时的那几个情况
            if(isN(line[i][j]))
            {
                if(j==length_char[i]-1)
                {
                    if(line[i][0]!=line[i][j])
                        vv[int(line[i][j])].insert(line[i][0]);
                }
                else if(isN(line[i][j+1])&&nullflag[int(line[i][j+1])]==1)
                {
                    if(line[i][0]!=line[i][j])
                        vv[int(line[i][j])].insert(line[i][0]);
                    for(set<char>::iterator ite2 = ww[int(line[i][j+1])].begin();ite2!=ww[int(line[i][j+1])].end();ite2++)
                    {
                        if(*ite2!='^')
                            ff[int(line[i][j])].insert(*ite2);
                    }
                }
                else if(isN(line[i][j+1])&&nullflag[int(line[i][j+1])]==0)
                {
                    for(set<char>::iterator ite2 = ww[int(line[i][j+1])].begin();ite2!=ww[int(line[i][j+1])].end();ite2++)
                    {
                        if(*ite2!='^')
                            ff[int(line[i][j])].insert(*ite2);
                    }
                }
                else if(isT(line[i][j+1]))
                {
                    ff[int(line[i][j])].insert(line[i][j+1]);
                }else{}
            }
            j++;
        }
    }


    while(!isEmpty())
    {
        for(set<char>::iterator ite1 = N.begin();ite1!=N.end();ite1++)
        {
            //对于所有非终结符
            //如果他的fllow已经完毕收集
            if(vv[int(*ite1)].empty())
            {
                //那么就把他的first加入到含有他的vv中
                for(set<char>::iterator ite3 = N.begin();ite3!=N.end();ite3++)
                {
                    for(set<char>::iterator ite4 = vv[int(*ite3)].begin();ite4!=vv[int(*ite3)].end();ite4++)
                    {
                        if(*ite4==*ite1)
                        {
                            vv[int(*ite3)].erase(*ite4);
                            //ite1的first集
                            for(set<char>::iterator ite5 = ff[int(*ite1)].begin();ite5!=ff[int(*ite1)].end();ite5++)
                            {
                              ff[int(*ite3)].insert(*ite5);
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}


SELECT集


void selectSet()
{
    for(int i=0;i<ll;i++)
    {
        int j=3;
        if(isN(line[i][3]))
        {
            for(set<char>::iterator ite2 = ww[line[i][3]].begin();ite2!=ww[line[i][3]].end();ite2++)
            {
                if(*ite2!='^')
                    select[i].insert(*ite2);
            }
        }
        while(isN(line[i][j])&&nullflag[int(line[i][j])]==1)
        {
            if(j==length_char[i]-1)
                break;
            for(set<char>::iterator ite2 = ww[line[i][j+1]].begin();ite2!=ww[line[i][j+1]].end();ite2++)
            {
                if(*ite2!='^')
                    select[i].insert(*ite2);
            }
            j++;
        }
        if(isT(line[i][j]))
        {
            select[i].insert(line[i][j]);
        }
    }

    _null2();
    for(int i=0;i<ll;i++)
    {
        if(nullselect[i]==1)
        {
            select[i].erase('^');
            for(set<char>::iterator ite5 = ff[int(line[i][0])].begin();ite5!=ff[int(line[i][0])].end();ite5++)
            {
                select[i].insert(*ite5);
            }
        }
    }
}

建表


void LL_1Table()
{
    for(int i=0;i<ll;i++)
    {
        for(set<char>::iterator ite2 = select[i].begin();ite2!=select[i].end();ite2++)
        {
            for(int j=0;j<length_char[i];j++)
                M[int(line[i][0])][int(*ite2)]+=line[i][j];
        }
    }
}

表分析


void grammatical_analysis(string s)
{
    cout<<"步骤  "<<"符号栈 "<<"剩余输入串  "<<"产生式(空用^表示)"<<endl;
    for(int i=0 ; i<s.length();i++)
    {   //初始化输入串队列
        qq.push(s[i]);
    }
    //分析过程
    while((qq.front()=='#'&&cc.top()=='#')==0)
    {
        while(isN(cc.top()))
        {
            string str=M[cc.top()][qq.front()];
            //错误1号
            if(str=="")
            {
                cout<<step<<" "<<"输入句不是文法的合法句型"<<endl;
                error_flag=1;
                break;
            }
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<str<<endl;
            cc.pop();
            for(int i=str.size()-1;i>=0;i--)
            {
                if(str[i]=='>')
                    break;
                if(str[i]!='^')
                cc.push(str[i]);
            }
        }
        //接受
        if(error_flag==1)
        {
            break;
        }
        if(cc.top()=='#'&&qq.front()=='#')
        {
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<"接受"<<endl;
        }
        else if(cc.top()==qq.front())
        {
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<"\""<<cc.top()<<"\"匹配"<<endl;
            qq.pop();
            cc.pop();
        }else{
            //错误2号
            cout<<step<<" "<<"输入句不是文法的合法句型"<<endl;
        }
    }
}

以上是整个的具体思路即核心代码

完整代码请见

点击打开链接



版权声明:本文为qq_18506419原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。