LL(1)语法分析器的实现

LL(1)语法分析器的实现

LL(1)分析器是由LL(1)分析表、语法符号栈和总控程序组成的。实现LL(1)分析器的首要步骤便是构造语法分析表,而语法分析表的构造要借助于头符号集First(α)和后继符号集Follow(A),所以问题的主要矛盾便成为如何实现First集和Follow集的求取。

1. First集的求取

First(x)有两种情况,第一种情况是x属于终极符和非终极符的并集(即x是单个符号),另外一种情况是x属于终极符和非终极符的闭包(即x=x1x2x3…).
①x属于单个字符:
.若x∈Vt,则First(x) = { x };
.若 x 属于Vn且有产生式x -> a…(a∈Vt),则将a加入First(x);
.若x -> 空符,则把空符也加进去;
.若x -> Y…,Y∈(Vn),则把 First(Y) - 空符 加入First(x)中;
.特别的,若x -> Y1Y2…Yk… ,判断First(Yi)是否能加入First(x)是看所有的 j < i First(Yj)是否含有空符,若所有的First(Yj)都含有空符才能将First(Yi) - 空符加入First(x),最后如果所有的First(Yi)含有空符才把空符加入到First(x)中去。
.
[注解]First(x) = { x 能推导出的所有终极符的集合(包含空符)}

先把第一种情况的First(x)代码实现出来:思路跟定义一致,需要注意的是处理
x->Y1Y2Y3…Yk这种情况,解决方法是First(Y1)-空符直接加进去即可,对于以后的每一个First(Yi)如果flag == 1,说明前面的所有First(Yj)都是含有空符的,所以是可以加进去的,然后判断此First(Yi)是否含有空符,从而决定是否还要继续下去。

void Fset::Full_First(char ch){
   
    //First集
	int tag = 0;    //记录能够推导出空符的Yi的个数
	int flag = 0;   //判断是否能够推导出空符
	if(IsVn(ch)){
      //是非终极符的情况
        for(int i = 0;i < length;i++)//i代表的是产生式的个数
        {
   
            if(gram[i].name==ch)//所求first(x)的x为 产生式的头部
            {
   
                for(int j=0;j<gram[i].tuidao.size();j++)
                {
      //对此产生式的右部进行操作
                    if(!IsVn(gram[i].tuidao[j]) && j == 0)//如果是终结符,则直接压入 x->a...  x属于Vn
                    {
   
                        first[Get_Nindex(ch)].insert(gram[i].tuidao[j]);//向first(x)中加入此非终极符
                        break;                              //保证只加一个
                    }
                    else if(IsVn(gram[i].tuidao[j]))
                    {
   		//如果是非终结符,则压入该非终结符的除了空集以外的元素
                        Full_First(gram[i].tuidao[j]);      //先求出此非终极符的first集
                        set<char>::iterator it;             //遍历此非终极符的first集
                        for(it = first[Get_Nindex(gram[i].tuidao[j])].begin();it!=first[Get_Nindex(gram[i].tuidao[j])].end();it++)
                        {
   
                            if(*it=='$')
                                flag = 1;                      //判断是否含有空符  即能否推导出空符
                            else
                                first[Get_Nindex(ch)].insert(*it);
                        }
                        if(flag == 0){
   
                            break;
                        }                         //有不能推导出空符的直接结束即可 前面的保证一定有空符的
                        else
                        {
   
                            tag += flag;
                            flag = 0;
                        }
                    }
                }
                if(tag == gram[i].tuidao.size())
                {
   						//最后判断空集是否应该被压入
                    first[Get_Nindex(ch)].insert('$');
                }
            }
        }
    }
    else{
   
        //x为终极符,直接令first(x)={ch}
        first[vnl + Get_Tindex(ch)].insert(ch);

    }
}

②x∈x1x2…xk:
.先将First(x1) - 空符加进First(x);
.此后对于每一个first(xi)如果所有的First(j) j<i都含有空符才能将First(xi) - 空符加入First(x);
.如果所有的First(xi)都含有空符,才可以将空符加入到First(x)中
.跟上面的最后一种情况差不多,直接来看代码

void Fset::Max_First(string ch, int pos){
   
    //first(x) x为多个符号的乘积  pos是用来支出存放的位置
    int flag = 0, tag = 0;
    //对待终极符和非终极符需要查找不同的位置
    if(IsVn(ch[0]))
    {
       //先求第一个字符的first集
        set<char>::itera
  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值