合肥工业大学(HFUT)编译原理实验三(Python实现)

一. 实验三: LR(1)分析法

二. 实验目的及要求

实现目的:

构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文

法识别的句子,了解LRK)分析方法是严格的从左向右扫描,和自底向上的

语法分析方法。

实验要求:

1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、如果遇到错误的表达式,应输出错误提示信息。

3、程序输入/输出实例:

输入一以#结束的符号串(包括+*()i#):在此位置输入符号串

输出过程如下:

三. 实验内容

对下列文法,用LR1)分析法对任意输入的符号串进行分析:

1E->E+T

2E->T

3T->T*F

4T->F

5F->(E)

6F->i

四. 核心算法流程

五.核心代码

def CLOSURE(mystr, num):  # 用于项目集内容的补充(找等价项目)

    my_dicts[num].append(mystr)  # 先加上它本身

    zhanwang = getSymbol(mystr)  # 再计算展望符

    # 遍历mystr 记录点后面那个字符

    for i in range(0, len(mystr)):

        if (mystr[i] == '.'):

            ch = mystr[i + 1]

    # 后面那个字符是非终结符

    if (ch in VNT):

        # 遍历非终结符ch的每个产生式

        for j in range(0, len(my_dict[ch])):

            #  取得非终结符ch的一个产生式的右部ch2

            ch2 = my_dict[ch][j]

            # 遍历展望符的每个元素

            for k in range(0, len(zhanwang)):

                mystr = ch + "->." + ch2 + "," + zhanwang[k]

                # 如果新的项目不在项目集中

                if (my_dicts[num].count(mystr) == 0):

                    my_dicts[num].append(mystr) # 添加

                # 如果ch2是一个非终结符 继续向下

                if (ch2[0] in VNT):

                    for ss in my_dict[ch2[0]]:

                        zhanwangs = getSymbol(mystr)

                        for kk in range(0, len(zhanwangs)):

                            mystr2 = ch2[0] + "->." + ss + "," + zhanwangs[kk]

                            if (my_dicts[num].count(mystr2) == 0):

                                CLOSURE(mystr2, num)

    else:

        return

def deleteI(delnum):  # 删除重复状态

    for i in delnum:

        del my_dicts[i]

# 往出指的过程

def DFA(mynum):

    # 用于存储新的状态集。

    newstr = []

    # 用于存储字符到状态集序号的映射。

    command = dict()

    global Inum

    # 遍历第mynum个项目集

    for fs in my_dicts[mynum]:  # 用字典存储 目标字符和状态集序号

        # 遍历一个项目(fs) 这个循环的目的是将左部填入

        for i in range(0, len(fs)):

            if (fs[i] == '.'): #规约项目

                if (fs[i + 1] == ','):

                    break

                else: # 产生式右部

                    # 如果新的项目集还没有存储这个点后面的元素

                    if (newstr.count(fs[i + 1]) == 0):

                        newstr.append(fs[i + 1])

                        # 增加项目集序号

                        Inum += 1

                        # 将字符映射到新的状态集序号

                        command[fs[i + 1]] = Inum

    # 再遍历一次

    for fs in my_dicts[mynum]:

        for i in range(0, len(fs)):

            if (fs[i] == '.'):

                if (fs[i + 1] == ','):

                    break

                else: #遇到点后面的元素

                    # 获取这个项目在新的项目集的编号

                    mynums = command[fs[i + 1]]

                    # s1是当前项目

                    s1 = list(fs)

                    # 交换位置(点和点后元素)

                    s1[i] = s1[i + 1]

                    # 在右部的开头加点

                    s1[i + 1] = '.'

                    # 转化为字符串

                    sq = ''.join(s1)  # 巧妙实现字符串的替换

                    CLOSURE(sq, mynums)  # 找等价项目

    delnum = []

    for key, value in command.items():

        for j in range(0, value):

            if (set(my_dicts[j]) == set(my_dicts[value])): # 如果两个状态集合相同

                command[key] = j  # 修改状态序号

                delnum.append(value)

    # 删除多余的集合

    deleteI(delnum)

    for key, value in command.items():

        end.append([mynum, key, value])

        numset.append(mynum)

        numset.append(value)  # 利用集合特性,修订状态数

六. 具体代码

        github仓库链接:https://github.com/1StephenCurry1/Compiler-Design.git

  • 12
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值