编译原理算符优先分析

时间:2021-10-14 03:57:57

程序代码如下:

#include <cstdio>
#include <set>
#include <cstdlib>
#include <cctype>
#include <functional>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#define esp 1e-6
using namespace std;
const int maxn = 1e5 + 7, mod = 1e9 + 7;

int prio_table[300][300];
vector<char>VN;
vector<char>VT;
bool vis_VN[30];
bool vis_VT[300];
bool LL_flag=true;
void init_visit()
{
    for(int i=0;i<26;i++)
        vis_VN[i]=true;
    for(int i=0;i<300;i++)
        vis_VT[i]=true; 
        
    for(int i=0;i<300;i++)
        for(int j=0;j<300;j++)
        {
            prio_table[i][j]=-2;
        }  
}

map<char,vector<string> >mp;//用来存文法 

bool is_VN(char x)//判断是否是非终结符 
{
    if(x>='A'&&x<='Z')
        return true;
    else
        return false;
}

bool is_VT(char x)
{
    return !is_VN(x);
}

set<char> FIRSTVT(char vnch)
{
    set<char>ans;
    for(int i=0;i<mp[vnch].size();i++)
    {
        string s=mp[vnch][i];
        if(!is_VN(s[0]))
            ans.insert(s[0]);
        else
        {
            if(s.length()>1)
                ans.insert(s[1]);
            if(s[0]!=vnch)
            {
                set<char>ss=FIRSTVT(s[0]);
                set<char>::iterator it;
                for(it=ss.begin();it!=ss.end();it++)
                {
                    ans.insert(*it);
                }
            }
        }
    }
    return ans;    
}

set<char> LASTVT(char vnch)
{
    set<char>ans;
    for(int i=0;i<mp[vnch].size();i++)
    {
        string s=mp[vnch][i];
        int s_end=s.length()-1;
        if(!is_VN(s[s_end]))
        {
            ans.insert(s[s_end]);
        }
        else
        {
            if(s_end>0)
                ans.insert(s[s_end-1]);
            if(s[s_end]!=vnch)
            {
                set<char>ss=LASTVT(s[s_end]);
                set<char>::iterator it;
                for(it=ss.begin();it!=ss.end();it++)
                {
                    ans.insert(*it);
                }
            }
        }
    }
    return ans;    
}

void show_FIRSTVT()
{
    for(int i=0;i<VN.size();i++)
    {
        cout<<VN[i]<<" : ";
        set<char>::iterator it;
        set<char>ss=FIRSTVT(VN[i]);
        for(it=ss.begin();it!=ss.end();it++)
        {
            cout<<(*it)<<"  ";
        }
        cout<<endl;    
    }
   
}

void show_LASTVT()
{
    cout<<"LASTVT:"<<endl;
    for(int i=0;i<VN.size();i++)
    {
        cout<<VN[i]<<" : ";
        set<char>::iterator it;
        set<char>ss=LASTVT(VN[i]);
        for(it=ss.begin();it!=ss.end();it++)
        {
            cout<<(*it)<<"  ";
        }
        cout<<endl;    
    }
    
}

void build_prio_table()
{
    char chf='#';
    set<char>::iterator itf;
    set<char>ss1=FIRSTVT(VN[0]);
    for(itf=ss1.begin();itf!=ss1.end();itf++)
    {
        prio_table[(int)chf][(*itf)]=-1;
    }
    set<char>ss2=LASTVT(VN[0]);
    for(itf=ss2.begin();itf!=ss2.end();itf++)
    {
        
        prio_table[(*itf)][(int)chf]=1;
    }
    prio_table[(int)chf][(int)chf]=0;
    
    
    for(int i=0;i<VN.size();i++)
    {
        for(int j=0;j<mp[VN[i]].size();j++)
        {
            string s=mp[VN[i]][j];
            for(int k=0;k<s.length();k++)
            {
                if(is_VT(s[k])&&k+1<s.length()&&is_VT(s[k+1]))//...ab...
                    prio_table[s[k]][s[k+1]]=0;
                if(is_VT(s[k])&&k+2<s.length()&&is_VN(s[k+1])&&is_VT(s[k+2]))//...aNb...
                    prio_table[s[k]][s[k+2]]=0;                    
                if(is_VT(s[k])&&k+1<s.length()&&is_VN(s[k+1]))//...aN...
                {
                    set<char>first=FIRSTVT(s[k+1]);
                    set<char>::iterator it;
                    for(it=first.begin();it!=first.end();it++)
                    {
                        prio_table[s[k]][(*it)]=-1;
                    }
                }
                if(is_VN(s[k])&&k+1<s.length()&&is_VT(s[k+1]))//...Na...
                {
                    set<char>last=LASTVT(s[k]);
                    set<char>::iterator it;
                    for(it=last.begin();it!=last.end();it++)
                    {
                        prio_table[(*it)][s[k+1]]=1;
                    }
                }
            }
        }
    }
    
}

void show_prio_table()
{
    cout<<"优先表如下:"<<endl; 
    cout<<" ";
    for(int i=0;i<VT.size();i++)
    printf("%10c",VT[i]);
    cout<<endl;
    for(int i=0;i<VT.size();i++)
    {
        cout<<VT[i];
        for(int j=0;j<VT.size();j++)
        {
            cout<<"         ";
            if(prio_table[VT[i]][VT[j]]==1)
                cout<<">";
            else if(prio_table[VT[i]][VT[j]]==0)
                cout<<"=";
            else if(prio_table[VT[i]][VT[j]]==-1) 
                cout<<"<";
            else
                cout<<" ";
        }
        cout<<endl;
    } 
}

set<string>scome;
 
int main() {
    init_visit(); 
    int k=1;
    char vn;
    string str;
    while(cin>>vn&&vn!='#'&&cin>>str)
    {
        if(vis_VN[vn-'A']==true)//不重复存vn 
        {
            VN.push_back(vn);
            vis_VN[vn-'A']=false;
        }        
        mp[vn].push_back(str);//代表vn可以推导出str
        for(int i=0;i<str.size();i++)
        {
            if(!is_VN(str[i])&&vis_VT[(int)str[i]]==true&&str[i]!='0')
            {
                VT.push_back(str[i]);
                vis_VT[(int)str[i]]=false;
            }
        }
        string sf=str;
        for(int i=0;i<sf.length();i++)
        {
            if(is_VN(sf[i]))
                sf[i]='N';
        }
        scome.insert(sf);  
    }
    VT.push_back('#');
    
    show_FIRSTVT();
    show_LASTVT();
    build_prio_table();
    show_prio_table();
    
    cout<<"input a string"<<endl;
    string checkstr;
    while(cin>>checkstr)
    {
        string stackstr="#";
        checkstr+='#';
        while(stackstr!="#N#")
        {
            cout<<stackstr;
            for(int i=1;i<30-stackstr.length()-checkstr.length();i++)
                cout<<" ";
            cout<<checkstr<<endl;
            char ch=checkstr[0];
            //无优先关系,error 
            if((is_VN(stackstr[stackstr.length()-1])&&prio_table[stackstr[stackstr.length()-2]][ch]==-2)||(is_VT(stackstr[stackstr.length()-1])&&prio_table[stackstr[stackstr.length()-1]][ch]==-2))
            {
                cout<<"error"<<endl;
                break;
            }
            //移入 
            if((is_VT(stackstr[stackstr.length()-1])&&prio_table[stackstr[stackstr.length()-1]][ch]<=0)||(is_VN(stackstr[stackstr.length()-1])&&prio_table[stackstr[stackstr.length()-2]][ch]<=0))
            {
                stackstr+=ch;
                checkstr.erase(checkstr.begin());
            }
            else
            {
                string test="";
                int strend=stackstr.length()-1;
                if(is_VN(stackstr[strend]))
                {
                    strend--;
                }
                int j;
                for(j=strend-1;j>=0;j--)
                {
                    if(is_VN(stackstr[j]))
                    {
                        j--;
                           if(prio_table[stackstr[j]][stackstr[j+2]]==-1)
                           {
                               break;
                           }
                    }
                    else
                    {
                        if(prio_table[stackstr[j]][stackstr[j+1]]==-1)
                           {
                               break;
                           }
                    }
                        
                }
                for(int k=j+1;k<stackstr.length();k++)
                    test+=stackstr[k];
                if(scome.count(test)==0)
                {
                    cout<<"error"<<endl;
                    break;
                }
                stackstr.erase(stackstr.begin()+j+1,stackstr.end());
                stackstr+='N'; 
                    
            }
        }
        if(stackstr=="#N#")
            cout<<"OK"<<endl;
        cout<<"input a string"<<endl;
    }
    
    return 0;
}

样例:

E E+T
E E-T
E T
T T*F
T T/F
T F
F (E)
F i
#

E E+T
E T
T T*F
T F
F P!F
F P
P i
P (E)
#