LR(1)文法分析器 //c++ 实现

1、先读入终结符,非终结符,和所有产生式。


2、预处理:初始化;getpp()获得每个非终结符在产生式左边时的产生式编号,
记录在 string getp[]中(可以多个)。


3.获得所有的符号的first集:dfs法,从S开始DFS,遇到终结符则是递归出口,回溯时候沿路保存记录所有路径上VN的first,(遇到有左递归的,continue,左递归的产生式不用不影响求fisrt集)


4:获得项目集族:一个lr(1)项目用一个结构体记录,get_close(项目 t):bfs来完成对t的闭包。getxmjizu():bfs,并用链式前向星记录图。


5.获得分析表table[][]:遍历对于图的所有边,状态i->j有权为w的边,置action(i,w)=j;go,本质是一样的.其次扫描所有项目,对于归约项目,置归约


6总控程序:俩个栈:状态栈和符号栈,无非移进、归约,接受保存。

测试:

a b
H S B
H->S
B->aB
S->BB
B->b
end


i * ( ) +
E T F
E->E+T
E->T
T->T*F
T->F
F->(E)
F->i
end


a b c d
S A B
S->A
A->B|cAd
B->aBb|ab
end


#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
mapgetnum;
char getchar[100];          //获得对应字符
vectorproce;        //产生式
int table[30][30];         //预测分析表 -1
int tb_s_r[30][30];        //是移进项还是规约项,-1,-2.
int num=0;int numvt=0;   //numvt是终结符集合,0是‘#’,numvt表空字
void readin()                        //读入vt,vn,编号1-num,读入所有产生式
{
    memset(table,-1,sizeof(table));
    getnum['#']=0;
    getchar[0]='#';
    cout<<"请输入终结符集:"<>x;
      getnum[x]=++num;
      getchar[num]=x;
    }while(cin.peek()!='\n');
     numvt=++num;
     getnum['@']=numvt;        //kong zi
     getchar[num]=('@');
    cout<<"请输入非终结符集:"<>x;
      getnum[x]=++num;
      getchar[num]=x;
    }while(cin.peek()!='\n');
    cout<<"输入所有产生式(空字用‘@’表示),以‘end’结束:"<>pro&&pro!="end")
     {
         string ss;
         ss+=pro[0];
         for(int i=3;i >v;             //项目集族
int e[100][3]; int head[100];int nume=0;    //链式前向星项目集族图
void addegde(int from,int to,int w)         //添加边
{
    e[nume][0]=to;e[nume][1]=head[from];head[from]=nume;
    e[nume++][2]=w;
}
void clear()                 //初始化函数
{
    for(int i=0;i<100;i++)
       head[i]=-1;
     for(int i=0;i<30;i++)
       for(int j=0;j<30;j++)
         tb_s_r[i][j]=table[i][j]=-1;
    nume=0;
}
inline bool xmeq(xiangmu a,xiangmu b)
{
    if(a.fst==b.fst&&a.id==b.id&&a.nump==b.nump)return 1;
    return 0;
}
bool isin(xiangmu a,vector b)      //xm a is in xmji b
{
    for(int i=0;i  hebing(vectora ,vectorb)  //合并项目集 a,b 复给 a
{
    for(int i=0;i a,vector b)  //两个项目集是否相等
{
    if(a.size()!=b.size())return 0;
     for(int i=0;ia,vector >b)  //查找项目集,若有,则返回编号,一举俩得
{
    for(int i=0;i get_close(xiangmu t)           //对项目 T作闭包
{
   vector temp;
   temp.push_back(t);
    queue q;                         //bfs完成闭包
    q.push(t);
    while(!q.empty())
    {
      xiangmu cur=q.front();
      q.pop();
      if(cur.id==proce[cur.nump].size())          //归约项舍去
          continue;
     int tt=getnum[proce[cur.nump][cur.id]];       //tt is thm num of '.'zhihoudefuhao
      if(tt<=numvt)   continue ;                  //若是终结符,则不必找了
      for(int i=0;iBC.D,a/b
          c.fst+=cur.fst;
         else                           //not the last  :A->B.CFb,a/b
        {
          int tttnum=getnum[proce[cur.nump][cur.id+1]];
          c.fst+=first[tttnum];
        }
         if(!isin(c,temp))           //排重,新的项目就加入。
         {
             q.push(c);
             temp.push_back(c);
         }
        }
      }
      return temp;
}
void get_xiangmujizu()             //获得项目集族
{
    vectortemp;
    xiangmu t;
    t.nump=0;t.id=1;t.fst+='0';    //初始的项目集:0
    temp=get_close(t);
    queue >q;        //bfs法获得
    q.push(temp);
    v.push_back(temp);             //第一个入
    while(!q.empty())
    {
         vector cur=q.front();
         q.pop();
         for(int i=1;i<=num;i++)     //所有符号
         {
             if(i==numvt)continue;      //'#'
             vector temp;
              for(int j=0;j"<j,读入符号W。
{
    for(int i=0;istate,stackwd,int i)
{
    cout<temp;
    while(!state.empty())
    {
        temp.push(state.top());
        state.pop();
    }
    while(!temp.empty())
    {
        cout<state;   //俩个栈:状态栈和符号栈
      stackwd;
      int count=0;
      state.push(0);     //初始化
      wd.push(0);        //'#'
    for(int i=0;;)       //i,读入文本的
    {
        int cur=state.top();
        if(table[cur][getnum[word[i]]]==-1)    // 空白,报错误
             return 0;
        if(table[cur][getnum[word[i]]]==-3)  //接受态
            {
                print_now_state(count++,state,wd,i);
                cout<<"      恭喜!acc!"<";
             for(int ii=1;ii<=len;ii++)
                 cout<>word;
   word+='#';
   if(!analyze())
       cout<<"error!"<



你可能感兴趣的:(编译原理)