编译原理 LL(1)文法分析程序详解

编译原理 LL(1)文法分析程序详解

在开始LL(1)文法分析之前,先要明白几个概念——first集、follow集、select集,下面分别介绍一下。

First集

设G=(Vt,Vn,P,S)是上下文无关文法。
First(α)={a | α⇒aβ,a∈Vt,a,β∈ V ∗ V^* V},若α⇒ ϵ \epsilon ϵ,规定 ϵ \epsilon ϵ∈First(α)。称First(α)为α的开始符号集或首符号集。
注意:α⇒aβ和α⇒ ϵ \epsilon ϵ中间推导过程可以是间接推导。

Follow集

设G=(Vt,Vn,P,S)是上下文无关文法。
A∈Vn,S是开始符号
Follow(A)={a | S⇒αAβ且a∈Vt,a∈First(β),α∈ V ∗ t V^*t Vt,β∈ V + V^+ V+},若S⇒αAβ,且β⇒ ϵ \epsilon ϵ,则#∈Follow(A)。
注意:S⇒αAβ和β⇒ ϵ \epsilon ϵ中间推导过程可以是间接推导。

Select集

一个产生式的选择符号集Select。给定上下文无法文法的产生式A->α,A∈Vn,α∈ V ∗ V^* V,若α不能直接或者间接推导出 ϵ \epsilon ϵ,则
Select(A->α)=First(α)。若α⇒ ϵ \epsilon ϵ,则Select(A->α)=First(α)-{ ϵ \epsilon ϵ} U Follow(A)。
注意:1. α⇒ ϵ \epsilon ϵ中间推导过程可以是间接推导。

LL(1)文法分析程序

文法例子(符合LL(1)文法)
A->TB
B->+TB
B->E
T->FC
C->*FC
C->E
F->i
F->(A)
第一步,求出能推出 ϵ \epsilon ϵ的非终结符。
1.首先建立一个以文法的非终结符个数为上界的一维数组,其数组元素为终结符,对应每一个非终结符有一个标记位,用以记录能否推出 ϵ \epsilon ϵ。其值有三种情况:“未定”,“是”,“否”。

enum 
{
    FU,//否
    SH,//是
    WD //未定
};

//规定E为空字符

vector<char>Vn;//非终结符
vector<char>Vt;//终结符
vector<char>V;//文法所有字符
vector<string>G;//文法
vector<string>G1;//文法副本
map<char, int>isEVn;//非终结符标记数组
//1 输入文法与初始化
string input;
void inputContextRule()
{
    while (cin >> input)
    {
        if (input == "#") break;
        G.push_back(input);
        G1.push_back(input);
    }

    int len = G1.size();
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < G1[i].size(); j++)
        {
        	//非终结符加入Vn
        	//将数组对应的每一非终结符的标记为"未定"
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E') { Vn.push_back(G1[i][j]); isEVn[G1[i][j]] = WD; }
            //终结符加入Vt
            if ((G1[i][j] > 'Z' || G1[i][j] < 'A')&&G1[i][j]!='|'&&G1[i][j] != '-' && G1[i][j] != '>') Vt.push_back(G1[i][j]);
        }
    }

    //去重
    set<int>se(Vt.begin(), Vt.end());
    Vt.assign(se.begin(), se.end());

    set<int>s(Vn.begin(), Vn.end());
    Vn.assign(s.begin(), s.end());
}

2.扫描文法中的产生式。
(1)删除所有右部含有终结符的产生式,若这使得以某一非终结符为左部的所有产生式都被删除,则将数组中对应该非终结符的标记值改为“否”,说明该非终结符不能推出 ϵ \epsilon ϵ
(2)若某一非终结符的某一产生式右部为 ϵ \epsilon ϵ,则将数组中对应该非终结符的标志置为“是”,并从文法中删除该非终结符的所有产生式。

void scamFuc()
{
    for (int i = 0; i < G1.size(); i++)
    {
        for (int j = 3; j < G1[i].size(); j++)
        {
            if ((G1[i][j] > 'Z' || G1[i][j] < 'A') && G1[i][j] != '|')
            { 
                G1[i]="";
                break;
            }
        }
    }

    int lenVn = Vn.size();
    for (int i = 0; i < lenVn; i++)
    {
        bool isexit = 0;
        for (int j = 0; j < G1.size(); j++)
        {
            if (Vn[i] == G1[j][0]) {
                isexit = 1;
                break;
            }
        }
        if (!isexit) {
            isEVn[Vn[i]] = FU;
        }
    }

    for (int i = 0; i < G1.size(); i++)
    {
        if (G[i].size() == 4 && G[i][3] == 'E')
        {
            isEVn[G[i][0]] = SH;
            for (int j = 0; j < G1.size(); j++)
            {
                if (G1[j][0] == G[i][0])
                {
                    G1[j] = "";
                }
            }
        }
    }
}

3.扫描产生式右部的每一个符号
(1)若扫描到的非终结符在数组中对应的标记是“是”,则删去该非终结符;若这时产生式右部为空,则将产生式左部的非终结符在数组中对应的标记改为“是”,并且删除以该非终结符位左部的所有产生式。
(2)若扫描到的非终结符在数组中对应的标记是“否”,则删去该产生式;若这使产生式左部非终结符的有关产生式都被删除,则把在数组中该非终结符对应的标记改成“否”。

void scamRight()
{
    for (int i = 0; i < G1.size(); i++)
    {
        for (int j =3; j < G1[i].size(); j++)
        {
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E' && isEVn[G1[i][j]] == SH)
            {
                char ch1 = G1[i][j];
                G1[i][j] = ' ';
                string se;
                bool isk = 1;
                for (int t = j; t < G[i].size(); t++)
                {
                    if (G1[i][j] != ' ')
                    {
                        isk = 0;
                    }
                }
                if (isk && G1[i][j - 1] == '>')
                {
                    isEVn[G1[i][0]] = SH;
                    for (int k = 0; k < G1.size(); k++)
                    {
                        if (G1[k][0] == ch1)
                        {
                            G1[k] = "";
                        }

                    }
                }
            }
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E' && isEVn[G1[i][j]] == FU)
            {
                bool isAlldel = 0;
                char ch = G1[i][0];
                G1[i] = "";
                for (int k = 0; k < G1.size(); k++)
                {
                    for (int t = 0; t < G1[k].size(); t++)
                    {

                        if (ch == G1[k][0])
                        {
                            isAlldel = 1;
                            break;
                        }
                    }
                }
                if (!isAlldel) {
                    isEVn[ch] = FU;
                }

            }
            
        }
    }
}

重复3,直到数组中该非终结符对应的特征不在改变。
第二步 计算First集
1.根据First集定义对每一文法符号X∈V,计算First(X)。
(1).若X∈Vt,则First(X)={X}。
(2).若X∈Vn,且有产生式X->a……,a∈Vt,则a∈First(X)。
(3).若X∈Vn,X-> ϵ \epsilon ϵ,则 ϵ \epsilon ϵ∈First(X)。

 int counts;
    for (int i =0;i< V.size(); i++)
    {
        if (0 != (counts = count(Vt.begin(), Vt.end(), V[i])))
        {
            First[V[i]] += V[i];
        }
        if (0 != (counts = count(Vn.begin(), Vn.end(), V[i])))
        {
            for (int j = 0; j < G.size(); j++)
            {
                   if (V[i] == G[j][0]) {
                        if (G[j][2] == '>' && (G[j][3] > 'Z' || G[j][3] < 'A') && G[j][3] != '|')
                        {
                            First[V[i]] += G[j][3];
                        }
                        if (G[j][2] == '>' && G[j][3] == 'E')
                        {
                            First[V[i]] += "E"; 
                        }
                    }
            }
        }
    }

(4)若X,Y1,Y2,……Yn∈,而有产生式X->Y1,Y2,……,Yi-1,⇒ ϵ \epsilon ϵ时(1<=i<=n),则First(Y1)-{ ϵ \epsilon ϵ},First(Y2)-{ ϵ \epsilon ϵ},……,First(Yi-1)-{ ϵ \epsilon ϵ},First(Yi)都包含在First(X)中。
(5)当(4)中所有Yi⇒ ϵ \epsilon ϵ时,则First(X)=First(Y1) U First(Y2) U……U First(Yn) U { ϵ \epsilon ϵ}
注意:所有推导都可以时间接推导。

 for (int j = 0; j < G.size(); j++)
    {
        bool isall = 1;
        for (int k = 0; k < G[j].size(); k++)
        {
            if (G[j][k]>= 'A' && G[j][k]<='Z'){}
            else if(G[j][k] == '-' || G[j][k] == '>' || G[j][k] == '|' || G[j][k] == '*' || G[j][k] == '(' || G[j][k] == ')'|| G[j][k] == '+'){}
            else if (G[j][k] == 'E')
            {
                isall = 0;
                break;
            }
            else
            {
                isall = 0;
                break;
            }
        }
        if (isall)
        {

            bool isall1 = 1;
            for (int i = 3; i < G[j].size(); i++)
            {
                if (isEVn[G[j][i]] != SH)
                {
                    isall1 = 0;
                    break;
                }
            }

            if (isall1)
            {
                for (int i = 3; i < G[j].size(); i++)
                {
                    First[G[j][0]] += First[G[j][i]];
                }
                First[G[j][0]] += 'E';
            }
            else
            {
                for (int i = 3; i < G[j].size(); i++)
                {
                    if (isEVn[G[j][i]] == SH)
                    {
                        First[G[j][i]].erase(remove(First[G[j][i]].begin(), First[G[j][i]].end(), 'E'), First[G[j][i]].end());
                        First[G[j][0]] += First[G[j][i]];
    f                    First[G[j][i]] += "E";
                    }
                    else
                    {
                        First[G[j][0]] += First[G[j][i]];
                        break;
                    }
                }
            }                           
        }       
    }

反复(2)-(5),直到每个符号的First集不再增大为止。
求完单个文法符号的First集,不难求出一个符号串的First集。
若符号串 α \alpha α V ∗ V^* V, α \alpha α=X1X2……Xn,当X1不能直接或者间接推导出 ϵ \epsilon ϵ,则置First( α \alpha α)=First(X1)。
若对任何j(1<=j<=i-1,2<=i<=n), ϵ \epsilon ϵ∈First(Xj), ϵ \epsilon ϵ不属于First(Xi),则First( α \alpha α)=U (First(Xj)-{ ϵ \epsilon ϵ}) U First(Xi)
当对任何j(1<=j<=n),First(Xj)都含有 ϵ \epsilon ϵ时,则First( α \alpha α)=U (First(Xj)) U { ϵ \epsilon ϵ}。

void calsMultiFirst()
{
    for (int i = 0; i < G.size(); i++)
    {
        string s;
        int k = 3;
        while (k<G[i].size())
        {
            s += G[i][k];
            k++;
        }

        if (isEVn[s[0]] == FU)
        {
            First1[s] = First[s[0]];
        }
        
        bool isall2 = 1;
        int saveks;
        for (int ks = 0; ks < s.size(); ks++)
        {
            if (-1 == First[s[ks]].find("E"))
            {
                isall2 = 0;
                saveks = ks;
                break;
            }
        }
        if (isall2)
        {
            for (int m = 0; m < s.size(); m++)
            {
                First1[s] = First1[s] + First[s[m]];
            }
            First1[s] = First1[s] + "E";
        }
        else
        {
            for (int t = 0; t < saveks; t++)
            {
                First[s[t]].erase(remove(First[s[t]].begin(), First[s[t]].end(), 'E'), First[s[t]].end());
                First1[s] = First1[s] + First[s[t]];
                First[s[t]] += "E";
            }
            First1[s] += First[s[saveks]];
        }
    }

    
}

第三步 计算Follow集
1 设S为文法的开始符号,把{#}加入到Follow(S)中。
2 若A-> α \alpha αB β \beta β是一个产生式,则把First( β \beta β)的非空元素加入到Follow(B)中。如果 β \beta β ϵ \epsilon ϵ,则把Follow(A)也加入到Follow(B)中。
3反复使用2直到每个非终结符的Follow集不在增大。

void initFollow() {
    

    Follow['A'] = "#";

    for (int i = 0; i < Vn.size(); i++)
    {
        if (Vn[i] != 'A')
        {
            Follow[Vn[i]] = "";
        }
    }
}
void calFollow()
{
    for (int i = 0; i < Vn.size(); i++)
    {
        for (int j = 0; j < G.size(); j++)
        {
            if (G[j][0] == Vn[i])
            {
                for (int k = 3; k < G[j].size(); k++)
                {
                    string s;
                    if (G[j][k] >= 'A' && G[j][k] <= 'Z'&& G[j][k]!='E')
                    {
                        for (int t = k+1; t < G[j].size(); t++)
                        {
                            s += G[j][t];
                        }
                        bool isa = 1;
                        for (int n = 0; n < s.size(); n++)
                        {
                            if (isEVn[s[n]] == 0)
                            {
                                isa = 0;
                                //break;
                            }
                        }
                        if (s.size() > 1)
                        {
                            if (First1[s] != "") {
                                for (int m = 0; m < First1[s].size(); m++)
                                {
                                    if (First1[s][m] != 'E') Follow[G[j][k]] += First1[s][m];
                                }
                                if (isa)
                                {
                                    Follow[G[j][k]] += Follow[Vn[i]];
                                }
                                //break;
                            }
                        }
                        else
                        {
                            if (s.size() == 0)
                            {
                                Follow[G[j][k]] += Follow[Vn[i]];
                                //break;
                            }
                            if (First[s[0]] != "")
                            {
                                for (int m = 0; m < First[s[0]].size(); m++)
                                {
                                    if (First[s[0]][m] != 'E') Follow[G[j][k]] += First[s[0]][m];
                                }
                                if (isa)
                                {
                                    Follow[G[j][k]] += Follow[Vn[i]];
                                }
                               // break;
                            }
                           
                        }  
                    }
                    
                  
                }
            }
        }

    } 
}

第四步 计算select集,根据select集的定义求。

void calselect()
{
    for (int i = 0; i < G.size(); i++)
    {
        string s;
        bool iss = 1;
        for (int j = 3; j < G[i].size(); j++)
        {
            s += G[i][j];
            if ((isEVn[G[i][j]] == FU||isEVn[G[i][j]]==0)&&G[i][j]!='E')
            {
                
               iss = 0;
            }
        }
        if (iss)
        {
            
            Select[G[i]] += Follow[G[i][0]];
            if (s.size() == 1) {
                First[s[0]].erase(remove(First[s[0]].begin(), First[s[0]].end(), 'E'), First[s[0]].end());
                Select[G[i]] += First[s[0]];
              
            }
            if(s.size() >1)
            {
                First1[s].erase(remove(First1[s].begin(), First1[s].end(), 'E'), First1[s].end());
                Select[G[i]] += First1[s];
              
            }
           
        }
        else
        {
            if (s.size() == 1)
            {
                Select[G[i]] = First[s[0]];
            }
            if (s.size() > 1)
            {
                Select[G[i]] = First1[s];
            }
            
        }
    }

    map<string, string>::iterator it;
    for (it = Select.begin(); it != Select.end(); ++it) {
        string ss = it->second;

        string sss;

        for (int i = 0; i < ss.size(); i++)
        {
            if (-1 == sss.find(ss[i]))
            {
                sss += ss[i];
            }
        }
        Select[it->first] = sss;
    }

    cout << "select集" << endl;
    for (it = Select.begin(); it != Select.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    cout << "_________________" << endl;
}

第五步 构造预测分析表
对每个终结符或‘#’号用a表示。
若a∈Select(A-> α \alpha α),则把A-> α \alpha α放到M[A][ α \alpha α]中。
把所有无定义的M[A][ α \alpha α]标上出错标记。

void makeanlysistable()
{
    Vt.push_back('#');
    for (int i = 0; i < Vt.size(); i++)
    {
        map<string, string>::iterator it;
        for (it = Select.begin(); it != Select.end(); it++)
        {
            
            if (Select[it->first].find(Vt[i])!=string::npos)
            {
                Anlysis[it->first[0]][Vt[i]] = it->first;
            }
        }
    }
   
    cout << "______________________" << endl;
    cout << "分析表" << endl;
    map<char, map<char, string>>::iterator its;
    for (its = Anlysis.begin(); its != Anlysis.end(); its++)
    {
        map<char, string>temp(its->second);
        map<char, string>::iterator it=temp.begin();
        for (; it != temp.end(); it++)
        {
            cout << its->first << "  " << it->first << "  " << it->second << endl;
        }
    }
}

第六步 构造分析栈

void finally(string s)
{
    stk.push('#');
    stk.push('A');
    int i = 0;
    while(i<s.size()){
        string temp;
        char c = stk.top();
        if (s[i] != c)
        {
            if (Anlysis[c][s[i]].size() == 0)
            {
                cout << "error" << endl;
                break;
            }
            for (int j = 0; j < Anlysis[c][s[i]].size(); j++)
            {
                if (j >= 3)
                {
                    temp += Anlysis[c][s[i]][j];
                }
            }
            stk.pop();
            if (temp[0] != 'E') {
                for (int t = temp.size() - 1; t >= 0; t--)
                {
                    stk.push(temp[t]);
                }
            }
           
        }
        else
        {
            if (c == '#' && s[i] == '#')
            {
                cout << "acc" << endl;
                break;
            }
            stk.pop();
            i++;
        }
    }
}

总结

把上面所有代码综合到一起

#include<iostream>
#include<ctype.h>
#include<vector>
#include<map>
#include<string>
#include<algorithm>
#include <set>
#include <stack>
using namespace std;

enum 
{
    FU, SH, WD
};

//规定E为空字符
vector<char>Vn;//非终结符
vector<char>Vt;//终结符
vector<char>V;//文法字符
vector<string>G;//文法
vector<string>G1;//文法副本
map<char, int>isEVn;//非终结符标记数组
map<char, string>First;//每个文法符号的first集
map<string, string>First1;//每个字符串的first集
map<char, string>Follow;//每个非终结符的follow集
map<string, string>Select;//select集
map<char,map<char,string>>Anlysis;// 分析表
stack<char>stk;

string input;

//第一步 输入文法与初始化
void inputContextRule()
{
    while (cin >> input)
    {
        if (input == "#") break;
        G.push_back(input);
        G1.push_back(input);
    }

    int len = G1.size();
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < G1[i].size(); j++)
        {
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E') { Vn.push_back(G1[i][j]); isEVn[G1[i][j]] = WD; }
            if ((G1[i][j] > 'Z' || G1[i][j] < 'A')&&G1[i][j]!='|'&&G1[i][j] != '-' && G1[i][j] != '>') Vt.push_back(G1[i][j]);
        }
    }

    //去重
    set<int>se(Vt.begin(), Vt.end());
    Vt.assign(se.begin(), se.end());

    set<int>s(Vn.begin(), Vn.end());
    Vn.assign(s.begin(), s.end());
}
void scamFuc()
{
    for (int i = 0; i < G1.size(); i++)
    {
        for (int j = 3; j < G1[i].size(); j++)
        {
            if ((G1[i][j] > 'Z' || G1[i][j] < 'A') && G1[i][j] != '|')
            { 
                G1[i]="";
                break;
            }
        }
    }

    int lenVn = Vn.size();
    for (int i = 0; i < lenVn; i++)
    {
        bool isexit = 0;
        for (int j = 0; j < G1.size(); j++)
        {
            if (Vn[i] == G1[j][0]) {
                isexit = 1;
                break;
            }
        }
        if (!isexit) {
            isEVn[Vn[i]] = FU;
        }
    }

    for (int i = 0; i < G1.size(); i++)
    {
        if (G[i].size() == 4 && G[i][3] == 'E')
        {
            isEVn[G[i][0]] = SH;
            for (int j = 0; j < G1.size(); j++)
            {
                if (G1[j][0] == G[i][0])
                {
                    G1[j] = "";
                }
            }
        }
    }
}
void scamRight()
{
    for (int i = 0; i < G1.size(); i++)
    {
        for (int j =3; j < G1[i].size(); j++)
        {
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E' && isEVn[G1[i][j]] == SH)
            {
                char ch1 = G1[i][j];
                G1[i][j] = ' ';
                string se;
                bool isk = 1;
                for (int t = j; t < G[i].size(); t++)
                {
                    if (G1[i][j] != ' ')
                    {
                        isk = 0;
                    }
                }
                if (isk && G1[i][j - 1] == '>')
                {
                    isEVn[G1[i][0]] = SH;
                    for (int k = 0; k < G1.size(); k++)
                    {
                        if (G1[k][0] == ch1)
                        {
                            G1[k] = "";
                        }

                    }
                }
            }
            if (G1[i][j] >= 'A' && G1[i][j] <= 'Z' && G1[i][j] != 'E' && isEVn[G1[i][j]] == FU)
            {
                bool isAlldel = 0;
                char ch = G1[i][0];
                G1[i] = "";
                for (int k = 0; k < G1.size(); k++)
                {
                    for (int t = 0; t < G1[k].size(); t++)
                    {

                        if (ch == G1[k][0])
                        {
                            isAlldel = 1;
                            break;
                        }
                    }
                }
                if (!isAlldel) {
                    isEVn[ch] = FU;
                }

            }
            
        }
    }
}
void OneStep() {
    inputContextRule();
    scamFuc();
    for (int i = 0; i < 3; i++) {
        scamRight();
    }
    cout << "______________"<< endl;
    map<char, int>::iterator it;
    for (it = isEVn.begin(); it != isEVn.end(); ++it) {
        cout << it->first << ' ' << it->second << endl;
    }
    cout << "______________" << endl;
}

//第二步 求First集
void SumV() {
    int isexit;
    for (int i = 0; i < Vn.size(); i++) 
    {
        if (0 == (isexit = count(V.begin(), V.end(), Vn[i])))
        {
            V.push_back(Vn[i]);
        }
    }
    for (int i = 0; i < Vt.size(); i++)
    {
        if (0 == (isexit = count(V.begin(), V.end(), Vt[i])))
        {
            V.push_back(Vt[i]);
        }
    }
}
void calSingleFirst()
{
    int counts;
    for (int i =0;i< V.size(); i++)
    {
        if (0 != (counts = count(Vt.begin(), Vt.end(), V[i])))
        {
            First[V[i]] += V[i];
        }
        if (0 != (counts = count(Vn.begin(), Vn.end(), V[i])))
        {
            for (int j = 0; j < G.size(); j++)
            {
                   if (V[i] == G[j][0]) {
                        if (G[j][2] == '>' && (G[j][3] > 'Z' || G[j][3] < 'A') && G[j][3] != '|')
                        {
                            First[V[i]] += G[j][3];
                        }
                        if (G[j][2] == '>' && G[j][3] == 'E')
                        {
                            First[V[i]] += "E"; 
                        }
                    }
            }
        }
    }
    for (int j = 0; j < G.size(); j++)
    {
        bool isall = 1;
        for (int k = 0; k < G[j].size(); k++)
        {
            if (G[j][k]>= 'A' && G[j][k]<='Z'){}
            else if(G[j][k] == '-' || G[j][k] == '>' || G[j][k] == '|' || G[j][k] == '*' || G[j][k] == '(' || G[j][k] == ')'|| G[j][k] == '+'){}
            else if (G[j][k] == 'E')
            {
                isall = 0;
                break;
            }
            else
            {
                isall = 0;
                break;
            }
        }
        if (isall)
        {

            bool isall1 = 1;
            for (int i = 3; i < G[j].size(); i++)
            {
                if (isEVn[G[j][i]] != SH)
                {
                    isall1 = 0;
                    break;
                }
            }

            if (isall1)
            {
                for (int i = 3; i < G[j].size(); i++)
                {
                    First[G[j][0]] += First[G[j][i]];
                }
                First[G[j][0]] += 'E';
            }
            else
            {
                for (int i = 3; i < G[j].size(); i++)
                {
                    if (isEVn[G[j][i]] == SH)
                    {
                        First[G[j][i]].erase(remove(First[G[j][i]].begin(), First[G[j][i]].end(), 'E'), First[G[j][i]].end());
                        First[G[j][0]] += First[G[j][i]];
                        First[G[j][i]] += "E";
                    }
                    else
                    {
                        First[G[j][0]] += First[G[j][i]];
                        break;
                    }
                }
            }                           
        }       
    }

   
}
void calsMultiFirst()
{
    for (int i = 0; i < G.size(); i++)
    {
        string s;
        int k = 3;
        while (k<G[i].size())
        {
            s += G[i][k];
            k++;
        }

        if (isEVn[s[0]] == FU)
        {
            First1[s] = First[s[0]];
        }
        
        bool isall2 = 1;
        int saveks;
        for (int ks = 0; ks < s.size(); ks++)
        {
            if (-1 == First[s[ks]].find("E"))
            {
                isall2 = 0;
                saveks = ks;
                break;
            }
        }
        if (isall2)
        {
            for (int m = 0; m < s.size(); m++)
            {
                First1[s] = First1[s] + First[s[m]];
            }
            First1[s] = First1[s] + "E";
        }
        else
        {
            for (int t = 0; t < saveks; t++)
            {
                First[s[t]].erase(remove(First[s[t]].begin(), First[s[t]].end(), 'E'), First[s[t]].end());
                First1[s] = First1[s] + First[s[t]];
                First[s[t]] += "E";
            }
            First1[s] += First[s[saveks]];
        }
    }

    
}
void TwoStep()
{
    SumV();
    for (int i = 0; i < 3; i++)
    {
        calSingleFirst();
    }
    
    map<char, string>::iterator it;
    for (it = First.begin(); it != First.end(); ++it) {
        string ss = it->second;

        string sss;

        if (it->first == 'E' ) First[it->first] += "E";
        for (int i = 0; i < ss.size(); i++)
        {
            if (-1 == sss.find(ss[i]))
            {
                sss += ss[i];
            }
        }
        First[it->first] = sss;
    }

    cout << "单字符first集" << endl;
    for (it = First.begin(); it != First.end(); ++it) {
        cout << it->first << ' ' << it->second << endl;
    }
    cout << "______________" << endl;

    for (int i = 0; i < 3; i++)
    {
        calsMultiFirst();
    }

    map< string, string>::iterator its;
    for (its = First1.begin(); its != First1.end(); ++its) {
        string ss = its->second;

        string sss;

        for (int i = 0; i < ss.size(); i++)
        {
            if (-1 == sss.find(ss[i]))
            {
                sss += ss[i];
            }
        }
        First1[its->first] = sss;
    }

    cout << "字符串frist集" << endl;
    for (its = First1.begin(); its != First1.end(); ++its) {
        cout << its->first << ' ' << its->second << endl;
    }
    cout << "______________" << endl;
}

//第三步 求Follow集
void initFollow() {
    

    Follow['A'] = "#";

    for (int i = 0; i < Vn.size(); i++)
    {
        if (Vn[i] != 'A')
        {
            Follow[Vn[i]] = "";
        }
    }
}
void calFollow()
{
    for (int i = 0; i < Vn.size(); i++)
    {
        for (int j = 0; j < G.size(); j++)
        {
            if (G[j][0] == Vn[i])
            {
                for (int k = 3; k < G[j].size(); k++)
                {
                    string s;
                    if (G[j][k] >= 'A' && G[j][k] <= 'Z'&& G[j][k]!='E')
                    {
                        for (int t = k+1; t < G[j].size(); t++)
                        {
                            s += G[j][t];
                        }
                        bool isa = 1;
                        for (int n = 0; n < s.size(); n++)
                        {
                            if (isEVn[s[n]] == 0)
                            {
                                isa = 0;
                                //break;
                            }
                        }
                        if (s.size() > 1)
                        {
                            if (First1[s] != "") {
                                for (int m = 0; m < First1[s].size(); m++)
                                {
                                    if (First1[s][m] != 'E') Follow[G[j][k]] += First1[s][m];
                                }
                                if (isa)
                                {
                                    Follow[G[j][k]] += Follow[Vn[i]];
                                }
                                //break;
                            }
                        }
                        else
                        {
                            if (s.size() == 0)
                            {
                                Follow[G[j][k]] += Follow[Vn[i]];
                                //break;
                            }
                            if (First[s[0]] != "")
                            {
                                for (int m = 0; m < First[s[0]].size(); m++)
                                {
                                    if (First[s[0]][m] != 'E') Follow[G[j][k]] += First[s[0]][m];
                                }
                                if (isa)
                                {
                                    Follow[G[j][k]] += Follow[Vn[i]];
                                }
                               // break;
                            }
                           
                        }  
                    }
                    
                  
                }
            }
        }

    } 
}
void ThridStep()
{
    initFollow();
    for (int i = 0; i <5; i++)
    {
        calFollow();
    }
    
    map<char, string>::iterator it;


    for (it = Follow.begin(); it != Follow.end(); ++it) {
        string ss = it->second;

        string sss;

        
        for (int i = 0; i < ss.size(); i++)
        {
            if (-1 == sss.find(ss[i]))
            {
                sss += ss[i];
            }
        }
        Follow[it->first] = sss;
    }

    cout << "非终结符的follow集" << endl;
    for (it = Follow.begin(); it != Follow.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    cout << "_________________" << endl;
}

//第四步 求select集
void calselect()
{
    for (int i = 0; i < G.size(); i++)
    {
        string s;
        bool iss = 1;
        for (int j = 3; j < G[i].size(); j++)
        {
            s += G[i][j];
            if ((isEVn[G[i][j]] == FU||isEVn[G[i][j]]==0)&&G[i][j]!='E')
            {
                
               iss = 0;
            }
        }
        if (iss)
        {
            
            Select[G[i]] += Follow[G[i][0]];
            if (s.size() == 1) {
                First[s[0]].erase(remove(First[s[0]].begin(), First[s[0]].end(), 'E'), First[s[0]].end());
                Select[G[i]] += First[s[0]];
              
            }
            if(s.size() >1)
            {
                First1[s].erase(remove(First1[s].begin(), First1[s].end(), 'E'), First1[s].end());
                Select[G[i]] += First1[s];
              
            }
           
        }
        else
        {
            if (s.size() == 1)
            {
                Select[G[i]] = First[s[0]];
            }
            if (s.size() > 1)
            {
                Select[G[i]] = First1[s];
            }
            
        }
    }

    map<string, string>::iterator it;
    for (it = Select.begin(); it != Select.end(); ++it) {
        string ss = it->second;

        string sss;

        for (int i = 0; i < ss.size(); i++)
        {
            if (-1 == sss.find(ss[i]))
            {
                sss += ss[i];
            }
        }
        Select[it->first] = sss;
    }

    cout << "select集" << endl;
    for (it = Select.begin(); it != Select.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    cout << "_________________" << endl;
}

//构造分析表
void makeanlysistable()
{
    Vt.push_back('#');
    for (int i = 0; i < Vt.size(); i++)
    {
        map<string, string>::iterator it;
        for (it = Select.begin(); it != Select.end(); it++)
        {
            
            if (Select[it->first].find(Vt[i])!=string::npos)
            {
                Anlysis[it->first[0]][Vt[i]] = it->first;
            }
        }
    }
   
    cout << "______________________" << endl;
    cout << "分析表" << endl;
    map<char, map<char, string>>::iterator its;
    for (its = Anlysis.begin(); its != Anlysis.end(); its++)
    {
        map<char, string>temp(its->second);
        map<char, string>::iterator it=temp.begin();
        for (; it != temp.end(); it++)
        {
            cout << its->first << "  " << it->first << "  " << it->second << endl;
        }
    }
}

//分析栈
void finally(string s)
{
    stk.push('#');
    stk.push('A');
    int i = 0;
    while(i<s.size()){
        string temp;
        char c = stk.top();
        if (s[i] != c)
        {
            if (Anlysis[c][s[i]].size() == 0)
            {
                cout << "error" << endl;
                break;
            }
            for (int j = 0; j < Anlysis[c][s[i]].size(); j++)
            {
                if (j >= 3)
                {
                    temp += Anlysis[c][s[i]][j];
                }
            }
            stk.pop();
            if (temp[0] != 'E') {
                for (int t = temp.size() - 1; t >= 0; t--)
                {
                    stk.push(temp[t]);
                }
            }
           
        }
        else
        {
            if (c == '#' && s[i] == '#')
            {
                cout << "acc" << endl;
                break;
            }
            stk.pop();
            i++;
        }
    }
}

//主程序
int main()
{
    OneStep();
    TwoStep();
    ThridStep();
    calselect();
    makeanlysistable();

    string inputs;
    cout << endl;
  
    while (true)
    {
        cout << "请输入串:" << endl;
        cin >> inputs;
        finally(inputs);
        cout << endl;
    }
   
    return 0;
}

可以参考《编译原理》第三版 ——清华大学出版社73-77,92-95,上面所有代码是根据上面的规则实现的。
毕竟水平有限,写的有错误的地方还请见谅。

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值