python实现文法左递归的消除方法


Posted in Python onMay 22, 2020

前言

  • 继词法分析后,又来到语法分析范畴。完成语法分析需要解决几个子问题,今天就完成文法左递归的消除。
  • 没借鉴任何博客,完全自己造轮子。

开始之前

  • 文法左递归消除程序的核心是对字符串的处理,输入的产生式作为字符串,对它的拆分、替换与合并操作贯穿始终,处理过程的逻辑和思路稍有错漏便会漏洞百出。
  • 采用直接改写法,不理解左递归消除方法很难读懂代码。

要求

  • CFG文法判断
  • 左递归的类型
  • 消除直接左递归和间接左递归
  • 界面

源码

import os
import tkinter as tk
import tkinter.messagebox
import tkinter.font as tf

zhuizhong = ""
wenfa = {"非左递归文法"}
xi_ = ""
huo = ""

window = tk.Tk()
window.title('消除左递归')
window.minsize(500,500)
#转换坐标显示形式为元组
def getIndex(text, pos):
  return tuple(map(int, str.split(text.index(pos), ".")))

def zhijie(x,y):
  if not len(y):
    pass
  else:
    if x == y[0]:
      wenfa.discard("非左递归文法")
      #处理直接左递归
      zuobian = y.split('|')
      feizhongjie = []
      zhongjie = []
      for item in zuobian:
        if x in item:
          item = item[1:]
          textt = str(item) + str(x) + "'"
          feizhongjie.append(textt)
        else:
          text = str(item) + str(x) + "'"
          zhongjie.append(text)
      if not zhongjie:#处理A -> Ax的情况
        zhongjie.append(str(x + "'"))
      cheng = str(x) + " -> " + "|".join(zhongjie)
      zi = str(x) + "'" + " -> " + "|".join(feizhongjie) + "|є"
      text_output.insert('insert','直接左递归文法','tag1')
      text_output.insert('insert','\n')
      text_output.insert('insert',cheng,'tag2')
      text_output.insert('insert','\n')
      text_output.insert('insert',zi,'tag2')
    '''
    加上会判断输出非递归产生式,但会导致间接左递归不能删除多余产生式
    else:
      h ="不变: " + x + " -> " + y
      text_output.insert('insert','非左递归文法','tag1')
      text_output.insert('insert','\n')
      text_output.insert('insert',h,'tag2')
    '''
    text_output.insert('insert','\n')

def zhijie2(x,y):
  if not len(y):
    pass
  else:
    if x == y[0]:
      wenfa.discard("非左递归文法")
      #处理直接左递归
      zuobian = y.split('|')
      feizhongjie = []
      zhongjie = []
      for item in zuobian:
        if x in item:
          item = item[1:]
          textt = str(item) + str(x) + "'"
          feizhongjie.append(textt)
        else:
          text = str(item) + str(x) + "'" 
          zhongjie.append(text)
      cheng = str(x) + " -> " + "|".join(zhongjie)
      zi = str(x) + "'" + " -> " + "|".join(feizhongjie) + "|є"
      text_output.insert('insert',"间接左递归文法",'tag1')
      text_output.insert('insert','\n')
      text_output.insert('insert',cheng,'tag2')
      text_output.insert('insert','\n')
      text_output.insert('insert',zi,'tag2')

    text_output.insert('insert','\n')

def tihuan(xk,yi,yk):
  yi_you = []
  yi_wu =[]
  yi_he = ""
  yi_wuhe = ""
  yi_zhong = ""
  yi_feizhong = []
  if xk in yi:
    yk_replace = yk.split('|')
    yi_fenjie = yi.split('|')#将含非终结与不含分开
    for ba in yi_fenjie:
      if xk in ba:
        yi_you.append(ba)
      else:
        yi_wu.append(ba)

    yi_he = "|".join(yi_you)

    for item in yk_replace:
      yi_zhong = yi_he.replace(xk,item)#替换
      yi_feizhong.append(yi_zhong)
    yi_wuhe = "|".join(yi_wu)#再合并
    global zhuizhong
    zhuizhong = "|".join(yi_feizhong) + "|" + yi_wuhe

#点击按钮后执行的函数
def changeString():
  text_output.delete('1.0','end')
  text = text_input.get('1.0','end')
  text_list = list(text.split('\n'))#一行一行的拿文法
  text_list.pop()
  if not text_list[0]:
    print(tkinter.messagebox.showerror(title = '出错了!',message='输入不能为空'))
  else:
    for cfg in text_list:
      
      x,y = cfg.split('->')#将文法左右分开
      x = ''.join(x.split())#消除空格
      y = ''.join(y.split())
      if not (len(x) == 1 and x >= 'A' and x <= 'Z'):
        pos = text_input.search(x, '1.0', stopindex="end")
        result = tkinter.messagebox.showerror(title = '出错了!',
        message='非上下文无关文法!坐标%s'%(getIndex(text_input, pos),))
        # 返回值为:ok
        print(result)
        return 0
      else:
        zhijie(x,y)
      
    for i in range(len(text_list)):
      for k in range(i):
        xi,yi = text_list[i].split('->')
        xi = ''.join(xi.split())#消除空格
        yi = ''.join(yi.split())
        
        xk,yk = text_list[k].split('->')
        xk = ''.join(xk.split())#消除空格
        yk = ''.join(yk.split())

        tihuan(xk,yi,yk)
        tihuan(xk,zhuizhong,yk)
        global xi_
        xi_ = xi
    zhijie2(xi_,zhuizhong)

    for item in wenfa:
      text_output.insert('insert',item,'tag1')  

    
#创建文本输入框和按钮
text_input = tk.Text(window, width=80, height=16)
text_output = tk.Text(window, width=80, height=20)
#简单样式
ft = tf.Font(family='微软雅黑',size=12)
text_output.tag_config("tag1",background="yellow",foreground="red",font=ft)
text_output.tag_config('tag2',font = ft)
#按钮
button = tk.Button(window,text="消除左递归",command=changeString,padx=32,pady=4,bd=4)
 
text_input.pack()
text_output.pack()
button.pack()
window.mainloop()

是不是很难懂,看看半吊子流程图主要流程

python实现文法左递归的消除方法

直接左递归

python实现文法左递归的消除方法

间接左递归合并

python实现文法左递归的消除方法

运行截图

python实现文法左递归的消除方法
python实现文法左递归的消除方法

总结

(1)确定方向

做一件事并不难,最难的是没有方向,不知道要做什么;只是感觉时光流逝自己却一点东西都没产出。幸好有具体的题目可供选择,这一次我稍有纠结之后,果断选择文法左递归消除,说实话,我认为这个最简单。

(2)开始实现

首先将消除左递归的方法理解透彻,找到了程序的本质就是对字符串的操作。
完成直接左递归算法非常顺利,我思路严谨步步为营,几乎没有bug,后续测试仅仅加上一些边缘情况的判断,比如空值,让程序面对复杂产生式也游刃有余。
将间接左递归的产生式合并的算法也很顺利,因为我在草稿纸上已经勾勒好了每一步需要得到什么,写代码时,一步一个输出,看是否符合预期,后续测试稍微小补增强健壮性。真正难点在于构思思路,就连最外层两个迭代都考虑了很久。
这两个算法的逻辑和思路是很复杂的,字符串的分分合合,分别存储,使用列表和字符串数据类型不下十个,再加上几个全局变量,我对自己清晰的思路略感自豪。

(3)不足之处
1、我希望能够实现,非左递归文法,左递归和间接左递归的一起输入一起识别一起消除,碰到非左递归文法就输出“非左递归文法”,然后将其不做任何修改输出。如果实现这个,如何让间接左递归不被当做非左递归文法处理呢?我没想到解决方案。
2、我对非终结符的判断采用的是是否包含,没有更进一步判断位置,比如消除 D -> Dh|sD|h,D在s后,这就不能很好的处理。
3、对于间接左递归文法产生式的输入顺序是有要求的,还没能做到随意输入。
(4)遇到的问题
我遇到的问题都是关于整体结构和取舍妥协,比如我最终选择将输入使用两个循环,一个是对一个个产生式进行迭代,消除直接左递归,第二个再从头采用下标嵌套两层循环来合并间接左递归。
在解决不足之处1时,我花了不少时间,用尽了方法,比如全局变量,集合,甚至还将代码备份,进行较大改动,最后还是妥协了。
在写两个核心算法的时候,我每一步拿到什么数据类型,拿到什么内容,都很小心的确认,一步一步推进,没出现“bug找一天”的情况。每到一步需要一个新的变量存储,我就在方法最开始加一个,tihuan()这个方法就有六个变量,现在想来,空间复杂度挺高。
(5)总结
这次的设计完全自主,没有借鉴任何博客,我也知道可能有些我认为很难的东西在大牛面前都不值一提,或许程序整体架构就差之甚远。无论如何,题目要求的东西我做到了,而且花的时间不算长,还是挺有成就感。但是,我绝对不会骄傲,根本没有骄傲的资本。
从画出界面,接收文本输入,取到产生式,判断类型,消除直接左递归,合并间接左递归再到消除间接左递归。有条有理,一步一个脚印,方能万丈高楼平地起。

到此这篇关于python实现文法左递归的消除方法的文章就介绍到这了,更多相关python文法左递归消除内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python 算法 排序实现快速排序
Jun 05 Python
Python中的条件判断语句与循环语句用法小结
Mar 21 Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
Apr 05 Python
sublime python3 输入换行不结束的方法
Apr 19 Python
Python实现的本地文件搜索功能示例【测试可用】
May 30 Python
利用python如何在前程无忧高效投递简历
May 07 Python
Python3 实现文件批量重命名示例代码
Jun 03 Python
Python实现EXCEL表格的排序功能示例
Jun 25 Python
python如何实现从视频中提取每秒图片
Oct 22 Python
python图片二值化提高识别率代码实例
Aug 24 Python
Windows环境下Python3.6.8 importError: DLLload failed:找不到指定的模块
Nov 01 Python
Python关于OS文件目录处理的实例分享
May 23 Python
使用Django搭建网站实现商品分页功能
May 22 #Python
Tensorflow卷积实现原理+手写python代码实现卷积教程
May 22 #Python
Python实现发票自动校核微信机器人的方法
May 22 #Python
基于django micro搭建网站实现加水印功能
May 22 #Python
基于Tensorflow一维卷积用法详解
May 22 #Python
Python参数传递机制传值和传引用原理详解
May 22 #Python
python filecmp.dircmp实现递归比对两个目录的方法
May 22 #Python
You might like
PHP中操作ini配置文件的方法
2013/04/25 PHP
php实现读取手机客户端浏览器的类
2015/01/09 PHP
CI框架出现mysql数据库连接资源无法释放的解决方法
2016/05/17 PHP
客户端静态页面玩分页
2006/06/26 Javascript
js中根据字数截取字符串,不能截断url
2012/01/12 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
jQuery消息提示框插件Tipso
2015/05/04 Javascript
jQuery实现向下滑出的二级菜单效果实例
2015/08/22 Javascript
jQuery实现自定义右键菜单的树状菜单效果
2015/09/02 Javascript
cocos2dx骨骼动画Armature源码剖析(三)
2015/09/08 Javascript
JavaScript实现的经典文件树菜单效果
2015/09/08 Javascript
JS阻止事件冒泡行为和闭包的方法
2016/06/16 Javascript
Angular中$cacheFactory的作用和用法实例详解
2016/08/19 Javascript
微信小程序 本地存储及登录页面处理实例详解
2017/01/11 Javascript
Angular2安装angular-cli
2017/05/21 Javascript
详解如何使用Node.js编写命令工具——以vue-cli为例
2017/06/29 Javascript
JavaScript学习笔记之DOM基础操作实例小结
2019/01/09 Javascript
Nodejs监听日志文件的变化的过程解析
2019/08/04 NodeJs
element-ui tooltip修改背景颜色和箭头颜色的实现
2019/12/16 Javascript
JS实现容器模块左右拖动效果
2020/01/14 Javascript
JS面向对象之单选框实现
2020/01/17 Javascript
mysql 之通过配置文件链接数据库
2017/08/12 Python
django启动uwsgi报错的解决方法
2018/04/08 Python
使用Python监控文件内容变化代码实例
2018/06/04 Python
python 保存float类型的小数的位数方法
2018/10/17 Python
python基于Selenium的web自动化框架
2019/07/14 Python
Python对wav文件的重采样实例
2020/02/25 Python
python GUI库图形界面开发之PyQt5单行文本框控件QLineEdit详细使用方法与实例
2020/02/27 Python
html5本地存储 localStorage操作使用详解
2016/09/20 HTML / CSS
HTML5视频播放插件 video.js介绍
2018/09/29 HTML / CSS
花卉与景观设计系大学生求职信
2013/10/01 职场文书
大学毕业通用个人的求职信
2013/12/08 职场文书
财务工作个人求职的自我评价
2013/12/19 职场文书
2015年度优秀员工自荐书
2015/03/06 职场文书
中学校园广播稿
2015/08/18 职场文书
公文格式,规则明细(新手收藏)
2019/07/23 职场文书