Python 实现预测分析

Python 对于文法的预测分析表进行预测分析

已知文法G(E):

E→TE’

E’→+TE’ |ε

T→FT’

T’→*FT’ |ε

F→(E) | i

先计算FIRST、FOLLOW、SELECT集合

计算方法见 链接: link.

检查是否能是LL(1)文法

通过SELECT集合
如:
select(A->bc)={a,b}
select(A->bd)={a,d}
因为select(A->bc) 并 select(A->bd) !=空
所以该文法不是LL(1)文法

非LL(1)文法到LL(1)文法的转换

如果存在左递归:
	S->Sa|ε
	那么消除左递归见 链接:[link](https://www.cnblogs.com/nano94/p/4020775.html)
如果存在左公共因子
	S->aB
	S-aC
	那么消除左公共因子见 链接 [link]:(https://blog.csdn.net/chen_dsir/article/details/72801574)

.

通过SELECT集和来构建预测分析表

预测分析表的构建见 连接:link.

基于已有的预测分析表进行预测分析

本文代码是基于已计算完毕的预测分析表进行预测分析,而不是对于文法直接进行预测文法

class G():
    # 初始化函数
    # 参数 Vn 非终结符集合
    # 参数 Vt 终结符集合 (集合的元素为字符串,存在E'这样的终结符)
    # 参数 dict_FAT 以二重字典形式存在的预测分析表
    # 字典的第一重的键值为非终结符 元素为字典
    # 字典的第二重的键值为终结符和# 元素为元组 元组中的每个字符串元素表示一个Vn或Vt
    # 例:dict={'P':{'a':['b','Q'], 'b':['a','P'], '#':['ε']},
    #           'Q':{'a':['c','E'], 'b':['a','Q'],'#':['a']}
    #           }
    def __init__(self, Vn, Vt, dict_FAT):
        self.Vn = Vn
        self.Vt = Vt
        self.dict = dict()
        for key in dict_FAT.keys():
            if key not in self.Vn:
                print('ketError! key:{:} not in Vn'.format(key))
            for key2 in dict_FAT[key].keys():
                if key2 not in self.Vt and key2 !='#':
                    print('ketError! key:{:} not in Vn'.format(key))
        self.dict = dict_FAT
    
    # 打印Vn Vt 和预测分析表
    def print(self):
        print('vn:{:}'.format(str(self.Vn)))
        print('vt:{:}'.format(str(self.Vt)))
        for key in self.dict.keys():
            print(key)
            for key2 in self.dict[key].keys():
                print('{:} {:}'.format(key2,self.dict[key][key2]),end=';')
            print()

    # 判断输入的字符串是否能通过预测分析
    def isAccept(self,string):
        stack_Ansy = [] # 分析栈
        stack_Ansy.append("#")
        stack_Ansy.append('E')  # 默认开始符为E
        list_str = list(string) # 输入栈
        while(stack_Ansy[len(stack_Ansy)-1] != '#' or list_str[0] != '#'): # 如果分析栈和输入栈的最后一个元素都为# 时 表示分析通过
            #print('{:50}'.format(" ".join(stack_Ansy)),end=' |  ')
            #print('{:50}'.format(" ".join(list_str)),end=' |  ')
            ansy = stack_Ansy.pop() # 分析栈出栈
            s = list_str[0] # 取输入字符
            if ansy == s:  # 如果分析栈弹出的元素等于当前读取的字符
                list_str = list_str[1:]  # 将字符串去掉第一个元素 切片操作
               # print('{:}=={:}'.format(ansy,s))
                continue
            try:  # 如果出现字典的keyError 那么表示出现了取空操作 那么存在不再分析表的的A a
                #print('{:5} {:5} '.format(ansy,s),end=' |  ')
                ss = self.dict[ansy][s] # 查询分析表 如果没用相应的A a那么抛出KeyError异常结束
               # print(ss)
                if ss != ['ε']: # 如果取出的产生式的右部不为空
                    ss.reverse()  # 将产生式逆置
                    stack_Ansy.extend(ss) # 将产生式压入分析栈
                    ss.reverse() # 恢复产生式的顺序0
            except BaseException as ke:
                #print(repr(ke))
                return False
        return True
        

if __name__ == '__main__':
    dict_FAT = { # 预测分析表
        'E':{'i': ['T','E`'], '(':['T','E`']},
        'E`':{'+': ['+','T','E`'], ')':['ε'], '#':['ε']},
        'T':{'i': ['F','T`'], '(':['F','T`']},
        'T`':{'+': ['ε'], '*':['*','F','T`'], ')':['ε'], '#':['ε']},
        'F':{'i': ['i'], '(':['(','E',')'] },
    }
    vn = ['E','E`','T','T`','F'] # 非终结符集合
    vt = ['i','+','*','(',')']  # 终结符集合
    g = G(vn, vt, dict_FAT)  # 创建文法对象
    accept = 'syntax correct'
    not_accpet = 'syntax error'
    strs = [] # 定义一个元组 存储即将输入的数据
    try:  # 循环输入 输入EOF时抛出异常结束输入
        string = input()
        while(string is not None): # 当输入的字符串不是空时
            strs.append(string) # 将输入的字符串加入到元组中
            string = input()  # 输入下一个字符串
    except BaseException: # 在Python 中如果输入Ctrl Z(EOF)那么input()将会抛出异常
        pass
    for s in strs: # 遍历输入的句子 检查是否能通过预测分析
        if g.isAccept(s): # 进行预测分析
            print(accept)
        else:
            print(not_accpet)

注释部分将输出分析过程

运行结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值