语法分析之自上而下分析:根据文法构造预测分析表环节(用python编写)

根据文法构造预测分析表

  • 自上而下分析:预测分析法的步骤一

预备介绍

语法分析部分的自上而下分析有两个方法,一个是递归分析法,另一个就是预测分析法。预测分析法最重要的一个环节就是构造预测分析表。接下来介绍一下如何用python来构造一个文法的预测分析表。

具体分析

构造过程会用到求文法符号的FIRST集、FOLLOW集,或者求符号串的FIRST集合的算法,可以参考之前发的一篇文章 点击此处跳转

首先介绍一下预测分析表的结构,简单来说他就是一张表,表的两个属性分别是非终结符和终结符(包括‘#’),形如:

abc(#
E
E’
F
F’
A

其中对应的内容是产生式的形式,若是没有产生式则可以写入标记来表示其匹配不到具体的产生式,进入报错处理程序。

根据文法构造预测分析表具体条件:
扫描全部产生式.
1.计算产生式的右部的FIRST集合,如果求出来的FIRST集合中包含终结符,那么就把这条产生式放入对应非终结符和终结符的格子中
2.如果ε在FIRST集合中,则计算该非终结符的FOLLOW集合,如果求出来的FOLLOW集合中包含终结符,那么就把这条产生式放入对应的非终结符和终结符的格子中

具体代码分析
接下来将对代码拆分分析,完整代码下载 点击此处跳转

在这里我定义形参lst,存储所有产生式,嵌套列表第一层为产生式,第二层为具体的每一条产生式,例如:

lst_demo = [["E","→","T","E","'"],["E","'","→","+","T","E","'","|","ε"],["T","→","F","T","'"],\
           ["T","'","→","*","F","T","'","|","ε"],["F","→","(","E",")","|","q"]]
# 根据文法构造预测分析表

import syntactic_parser_demo
import string

# 形参lst为文法的所有产生式,返回值为预测分析表table,其中最后两个元素分别为非终结符列表和终结符列表
def get_table(lst):

这里定义返回值为预测分析表table,其结构为一个嵌套列表,外层列表按照非终结符的顺序,内存列表按终结符的顺序。因此配合的,就要提前构造非终结符列表和终结符列表,来作为顺序。

	s = [] # 非终结符列表
    l = [] # 终结符列表
    punc = string.punctuation
    # 获取非终结符和终结符列表
    for i in lst:
        s.append("".join(i[:i.index('→')]))
        for j in i:
            if j.islower() or (j in punc) and (j not in l) and (j != "'") and (j != '|'):
                if j == 'ε':
                    l.append('#')
                else:
                    l.append(j)
    l = list(set(l))
    max_length = max(len(s),len(l))
    # 定义预测分析表,以嵌套列表的形式存储,[[1,2,3],[],[]]外层列表按非终结符的顺序,内层列表按终结符的顺序
    table = [['!' for i in range(max_length)] for i in range(max_length)]

有话说: 这里定义了一个空的嵌套列表,并且全部赋值为 ‘!’

获取接下来要用到的FOLLOW集合

follow = syntactic_parser_demo.get_follow(lst)

接下来判定的逻辑代码挺简单:

for p in lst:
        temp_s = "".join(p[:p.index('→')])
        one = s.index(temp_s) # 获取外层列表索引值
        temp_split = [] # 将每一个产生式分割以便求的长度来进行分类讨论
        # 获取这一条产生式的所有'|'的索引值
        temp_or = []
        temp_push = []
        for k in range(len(p)):
            if p[k] == '|':
                temp_or.append(k)
        # 获取这一条产生式'→'的索引值
        temp_get = p.index('→')
        # 转换成列表方便组合
        temp_push.append(temp_get)
        # 合并查找索引列表
        temp_search =  temp_push + temp_or
        # 把一个产生式以'→'和'|'为分隔符分割,将分割后的数据存储在嵌套列表temp_split里
        for m in range(len(temp_search)):
            if len(temp_search) == 1:
                temp_split = [p[temp_search[m] + 1:]]
            else:
                if m == (len(temp_search) - 1):
                    temp_split.append(p[temp_search[m] + 1:])
                else:
                    temp_split.append(p[temp_search[m] + 1:temp_search[m + 1]])
        for n in temp_split:
            temp_first = syntactic_parser_demo.get_first_bunch("".join(n),lst)
            for q in temp_first:
                if q != 'ε':
                    two = l.index(q) # 获取内层列表索引值
                    table[one][two] = temp_s.split() + ['→'] + n
            if 'ε' in temp_first:
                temp_follow = follow[temp_s]
                for z in temp_follow:
                    two = l.index(z)
                    table[one][two] = temp_s.split() + ['→'] + n
    table.append(s)
    table.append(l)
    return table

可供测试的代码:

if __name__ == '__main__':
    lst_demo = [["E","→","T","E","'"],["E","'","→","+","T","E","'","|","ε"],["T","→","F","T","'"],\
           ["T","'","→","*","F","T","'","|","ε"],["F","→","(","E",")","|","q"]]
    get_table(lst_demo)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
预测分析驱动的语法分析算法是一种自底向上的语法分析方法,用于分析给定输入串是否符合给定文法的规则。其主要思想是构造一个预测分析,将文法的非终结符和终结符作为的行和列,中的每个单元格存储了应该使用的产生式。算法在分析过程中通过栈来存储已经分析的串。 实现该算法的步骤如下: 1. 构造预测分析。 - 对文法的每个产生式 A->α,找到非终结符A的FIRST集合,将A->α加入到[A, a]中的所有a的位置。 - 若非终结符A可以推导出空串ε,对于文法的每个终结符b,将A->ε加入到[A, b]中的所有b的位置。 - 对于每个非终结符A,将A->ε加入到[A, $]中的位置。 2. 初始化栈。 - 将文法的开始符号S和输入串首部符号$依次入栈。 3. 预测分析过程。 - 若栈顶符号为非终结符X,当前输入符号为a,则查找预测分析[X, a]中的产生式X->α。 - 若产生式不存在,则抛出错误。 - 将栈顶符号X出栈,并将α逆序入栈。 - 若栈顶符号为终结符,且与当前输入符号匹配,则将栈顶符号和当前输入符号都出栈,继续下一步分析。 - 若栈顶符号为$,且当前输入符号为$,则分析成功。 - 若栈顶符号为$,但当前输入符号不为$,或者栈为空,则抛出错误。 该算法的时间复杂度为O(n),其中n为输入串的长度。该算法可以高效地进行语法分析,能够准确判断给定输入串是否符合文法规则。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

x1Nge.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值