Python实现LR1文法的完整实例代码


Posted in Python onOctober 25, 2020

一、使用步骤

 1.引入库(安装Python环境、PyQt、PyQt-tools)

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import datetime
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QHeaderView
from collections import defaultdict
import numpy as np

2.全局变量

#text = "E -> E + T \nE -> T\nT -> T * F\nT -> F\nF ->(E)\nF -> i"
#text = "S -> BB\nB -> aB\nB -> b"
my_dict = defaultdict(list)#记录各个终结符的产生式
my_dicts = defaultdict(list)#代表每组项目,暂时存储
VNT = []
VT = set([])
MAX = 50 #生成最多的项目集个数
Inum = 0 #记录项目集的个数
end = [] #记录,上一个状态数,通过的字符,下一个状态数[最终结果]
numset = []#列表,修订状态数 
endstate = [] #最终存储项目集镞 [最终结果]
guiyue = [] #记录每条文法

3.完整代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'LR1.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import datetime
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QHeaderView
from collections import defaultdict
import numpy as np
#text = "E -> E + T \nE -> T\nT -> T * F\nT -> F\nF ->(E)\nF -> i"
#text = "S -> BB\nB -> aB\nB -> b"
my_dict = defaultdict(list)#记录各个终结符的产生式
my_dicts = defaultdict(list)#代表每组项目,暂时存储
VNT = []
VT = set([])
MAX = 50 #生成最多的项目集个数
Inum = 0 #记录项目集的个数
end = [] #记录,上一个状态数,通过的字符,下一个状态数[最终结果]
numset = []#列表,修订状态数 
endstate = [] #最终存储项目集镞 [最终结果]
guiyue = [] #记录每条文法
def isTerminal(c): # 若c介于A-Z之间则认为是非终结符(注意添加 self参数)
  if c < 'A' or c > 'Z':
   return True
  else:
   return False
def SplitText(text): # 把文法中E->A|B 切分为E->A和E->B
 mytext = ""
 for i in text:
  if(i != ' '):#删除字符串的空格
   mytext += i;
 i = mytext.split('\n')
 guiyue.append(text[0]+"'->"+text[0])
 for j in i:
  if(VNT.count(j[0])==0):#没出现过的终结符
   VNT.append(j[0]) 
  for k in range(1,len(j)):
   if(j[k]=='-' and j[k+1]=='>'):
    k = k+2
    break
  guiyue.append(j)
  my_dict[j[0]].append(j[k:])
def getFirst(mylist):#计算目标字符串的Frist集
 Zlist = []
 for i in mylist:
  if(i not in VNT):
   Zlist.append(i)
   return Zlist
  else:
   for j in my_dict[i]: #遍历非终结符的产生式
    #print(j)
    if(j[0] == i):
     continue
    time = 0
    for ch in j:
     if(ch not in VNT):
      Zlist.append(ch)
      break
     else:
      Firstlist = getFirst(ch)#递归得到Frist集
      if 'ε' in Firstlist: # Firstlist其实是指一个list
        time += 1
      else:
       for vi in Firstlist:
        Zlist.append(vi)
    if(time == len(j)):
     Zlist.append('ε')
   return Zlist

def getSymbol(mystr):#根据Frist集得到下一个状态的展望符
 for i in range(0,len(mystr)):
  if(mystr[i] =='.'):
   mylist = list(mystr[i+2:])
   break
 Zlist = ['#']
 if(mylist[0]==','):
  mylist = mylist[1:]
 if(mylist[0]=='#'):
  VT.add('#')
  return Zlist
 a = getFirst(mylist)
 VT.update(set(a))
 return a #存储展望符
#print(getSymbol('E->.E+T,#'))#验证展望符是否正确

def CLOSURE(mystr,num): #用于项目集内容的补充
 my_dicts[num].append(mystr) #先加上它本身
 zhanwang = getSymbol(mystr)#再计算展望符
 for i in range(0,len(mystr)):
  if(mystr[i] =='.'):
   ch = mystr[i+1]
 if(ch in VNT):
  for j in range(0,len(my_dict[ch])):
   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)
    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
 for fs in my_dicts[mynum]: #用字典存储 目标字符和状态集序号
  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 = list(fs)
     s1[i] = s1[i+1]
     s1[i+1]='.'
     sq = ''.join(s1) #巧妙实现字符串的替换
     CLOSURE(sq,mynums) #生成新的状态集
 #print(command)
 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)
 #print(delnum)
 deleteI(delnum)
 for key,value in command.items():
  #print(mynum,'(',key,')->',value)
  end.append([mynum,key,value])
  numset.append(mynum)
  numset.append(value) #利用集合特性,修订状态数     

class Ui_Form(object):
 def setupUi(self, Form):
  Form.setObjectName("Form")
  Form.resize(994, 824)
  self.textBrowser = QtWidgets.QTextBrowser(Form)
  self.textBrowser.setGeometry(QtCore.QRect(520, 770, 461, 51))
  self.textBrowser.setObjectName("textBrowser")
  self.textBrowser_2 = QtWidgets.QTextBrowser(Form)
  self.textBrowser_2.setGeometry(QtCore.QRect(25, 771, 421, 41))
  self.textBrowser_2.setObjectName("textBrowser_2")
  self.label = QtWidgets.QLabel(Form)
  self.label.setGeometry(QtCore.QRect(460, 770, 51, 41))
  self.label.setObjectName("label")
  self.tabWidget = QtWidgets.QTabWidget(Form)
  self.tabWidget.setGeometry(QtCore.QRect(20, 240, 941, 521))
  self.tabWidget.setObjectName("tabWidget")
  self.First = QtWidgets.QWidget()
  self.First.setAccessibleName("")
  self.First.setObjectName("First")
  self.tableView = QtWidgets.QTableView(self.First)
  self.tableView.setGeometry(QtCore.QRect(10, 10, 911, 471))
  self.tableView.setObjectName("tableView")
  self.tabWidget.addTab(self.First, "")
  self.Analyse = QtWidgets.QWidget()
  self.Analyse.setObjectName("Analyse")
  self.tableView_2 = QtWidgets.QTableView(self.Analyse)
  self.tableView_2.setGeometry(QtCore.QRect(10, 10, 911, 471))
  self.tableView_2.setObjectName("tableView_2")
  self.tabWidget.addTab(self.Analyse, "")
  self.Process = QtWidgets.QWidget()
  self.Process.setObjectName("Process")
  self.tableView_3 = QtWidgets.QTableView(self.Process)
  self.tableView_3.setGeometry(QtCore.QRect(10, 10, 911, 471))
  self.tableView_3.setObjectName("tableView_3")
  self.tabWidget.addTab(self.Process, "")
  self.States = QtWidgets.QWidget()
  self.States.setObjectName("States")
  self.textBrowser_3 = QtWidgets.QTextBrowser(self.States)
  self.textBrowser_3.setGeometry(QtCore.QRect(10, 10, 911, 471))
  self.textBrowser_3.setObjectName("textBrowser_3")
  self.tabWidget.addTab(self.States, "")
  self.label_2 = QtWidgets.QLabel(Form)
  self.label_2.setGeometry(QtCore.QRect(40, 10, 51, 41))
  self.label_2.setObjectName("label_2")
  self.textEdit = QtWidgets.QTextEdit(Form)
  self.textEdit.setGeometry(QtCore.QRect(33, 46, 441, 181))
  self.textEdit.setObjectName("textEdit")
  self.textEdit.setText("E -> E + T \nE -> T\nT -> T * F\nT -> F\nF ->(E)\nF -> i")
 #初始化,编译原理测试数据
  #self.textEdit.setText("S -> BB\nB -> aB\nB -> b")
  self.lineEdit = QtWidgets.QLineEdit(Form)
  self.lineEdit.setGeometry(QtCore.QRect(640, 200, 271, 41))
  self.lineEdit.setObjectName("lineEdit")
  self.lineEdit.setText("i*i+i#")
 #初始化,编译原理测试数据
  self.label_3 = QtWidgets.QLabel(Form)
  self.label_3.setGeometry(QtCore.QRect(550, 200, 81, 41))
  self.label_3.setObjectName("label_3")
  self.pushButton = QtWidgets.QPushButton(Form)
  self.pushButton.setGeometry(QtCore.QRect(650, 110, 251, 71))
  self.pushButton.setObjectName("pushButton")
  self.pushButton.clicked.connect(self.Runs) # 将按钮与函数Runs()绑定,启动主程序
  self.retranslateUi(Form)
  self.tabWidget.setCurrentIndex(0)
  QtCore.QMetaObject.connectSlotsByName(Form)

 def retranslateUi(self, Form):
  _translate = QtCore.QCoreApplication.translate
  Form.setWindowTitle(_translate("Form", "LR(1)文法"))
  self.label.setText(_translate("Form", "分 析:"))
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.First), _translate("Form", "FIRST集"))
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.Analyse), _translate("Form", "分 析 表"))
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.Process), _translate("Form", "分 析 过 程"))
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.States), _translate("Form", "项 目 集 族"))
  self.label_2.setText(_translate("Form", "文 法:"))
  self.label_3.setText(_translate("Form", "输 入 框"))
  self.pushButton.setText(_translate("Form", "运 行 程 序"))
 def Runs(self):
  global VNT,VT,numset,Inum,endstate,guiyue,my_dict,my_dicts,end#初始化
  Inum = 0 #记录项目集的个数
  my_dict = defaultdict(list)#记录各个终结符的产生式
  my_dicts = defaultdict(list)#代表每组项目,暂时存储
  VNT = []
  VT = set([])
  end = [] #记录,上一个状态数,通过的字符,下一个状态数
  numset = []#列表,修订状态数 [最终结果]
  endstate = [] #最终存储项目集镞 [最终结果]
  guiyue = [] #记录每条文法
  times = datetime.datetime.now()
  times_str = times.strftime('  %Y-%m-%d %H:%M:%S')
  self.textBrowser_2.setText('运 行 时 间:'+times_str)
  text = self.textEdit.toPlainText()
  SplitText(text)#1 处理文法
  input0 = text[0]+"'->."+text[0]+',#' #输入第一个项目
  CLOSURE(input0,0) #2 生成I0项目集
  for i in range(0,MAX):
   DFA(i)
  numset = list(set(numset))#3 消除重复元素
  for i in end:#4 修订状态过程
   i[0] = numset.index(i[0])
   i[2] = numset.index(i[2])
  for i in range(0,len(my_dicts)):
   if my_dicts[i] != []:
    endstate.append(my_dicts[i])#5 将修订后的项目集族写入新的列表
  #将项目集族写入图形界面
  self.textBrowser_3.setText("\t\t\tLR(1)项 目 集 族\n")
  j = 0
  for i in endstate:
   self.textBrowser_3.append('I'+str(j)+': '+str(i)+'\n')
   j += 1
  #将Frist集写入图形界面
  self.model = QStandardItemModel(len(VNT), 5)
  label_y = []
  for s in VNT:
   label_y.append(s)
  self.model.setVerticalHeaderLabels(label_y)
  for row in range(len(VNT)):
    flist = [VNT[row]]#First集要输入一个列表
    Flist = list(set(getFirst(flist)))
    for column in range(len(Flist)):
     item = QStandardItem(Flist[column])
     self.model.setItem(row, column, item)
  self.tableView.horizontalHeader().setStretchLastSection(True)
  self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  self.tableView.setModel(self.model)
  #构造分析表,写入图形界面
  VT.discard('#')
  VT = list(VT) #先删除#
  VT.append('#')#想让#在ACTION表最后一列
  label_x = ['状 态']+VT+VNT
  self.model2 = QStandardItemModel(len(endstate),len(VNT)+len(VT))
  self.model2.setHorizontalHeaderLabels(label_x)
  label_y = []
  for i in range(0,len(endstate)):
   label_y.append(str(i))
  self.model2.setVerticalHeaderLabels(label_y)
  ACTION = [['0'] * len(VT) for i in range(len(endstate))] #存储分析表内容,为分析过程做准备
  GOTO = [['0'] * len(VNT) for i in range(len(endstate))]
  for q in end: #移进动作
   if(q[1] not in VNT):
    ss = 's'+str(q[2])
    ACTION[int(q[0])][VT.index(q[1])] = ss
   else:
    ss = str(q[2])
    GOTO[int(q[0])][VNT.index(q[1])] = ss
   item = QStandardItem(ss)
   self.model2.setItem(int(q[0]),label_x.index(q[1]),item)
  endstr = text[0]+"'->"+text[0]+'.,#' #终结标志
  for i in range(len(endstate)):#规约动作
   for j in range(len(endstate[i])):
    for k in range(len(endstate[i][j])):
     if(endstate[i][j][k]=='.'):
      if(endstate[i][j][k+1]== ','):
       #print(guiyue)
       ii = guiyue.index(endstate[i][j][:k])
       item = QStandardItem("r"+str(ii))
       ACTION[i][VT.index(endstate[i][j][k+2])] = "r"+str(ii)
       self.model2.setItem(i,label_x.index(endstate[i][j][k+2]),item)
   if(endstate[i][0] == endstr):
    item = QStandardItem("acc")#结束
    self.model2.setItem(i,label_x.index('#'),item)    
  self.tableView_2.horizontalHeader().setStretchLastSection(True)
  self.tableView_2.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  self.tableView_2.setModel(self.model2)
  self.model3 = QStandardItemModel(32,4)
  #print(ACTION)
  #print(GOTO)
  mystate = [0]#状 态
  stack = '#' #符 号
  inputstr = self.lineEdit.text()#输 入 串
  label_x = ['状 态', '符 号', '输 入 串', '动 作']
  self.model3.setHorizontalHeaderLabels(label_x)
  tabnum = 0
  while(1):
   self.model3.setItem(tabnum,0,QStandardItem(str(mystate)))
   self.model3.setItem(tabnum,1,QStandardItem(stack))
   self.model3.setItem(tabnum,2,QStandardItem(inputstr))
   tabnum += 1
   if(inputstr[0] not in VT):
    self.textBrowser.setText('报 错!')
   else:
    ch = ACTION[mystate[-1]][VT.index(inputstr[0])]#读取action值
   if(ch =='r0'):#本质就是acc
    self.textBrowser.setText('分 析 成 功!')
    break
   if(ch == '0'):
    self.textBrowser.setText('报 错!')
    break
   if(ch[0] == 's'):
    mystate.append(int(ch[1:]))#状态加一个
    stack += inputstr[0]#移进
    inputstr = inputstr[1:]#相当于删除第一个元素
   if(ch[0] == 'r'):
    gylist = guiyue[int(ch[1:])].split('->')
    g1 = str(gylist[1])[::-1]
    g0 = str(gylist[0])[::-1]
    gstack = stack[::-1]#逆序解决规约问题
    gstack = gstack.replace(g1,g0,1)
    stack = gstack[::-1]#完成规约任务
    strlen = len(gylist[1]) #计算长度
    for i in range(strlen):
     mystate.pop()#连续出栈
    mystate.append(int(GOTO [mystate[-1]] [VNT.index(gylist[0])] ))
  self.tableView_3.horizontalHeader().setStretchLastSection(True)
  self.tableView_3.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  self.tableView_3.setModel(self.model3)
if __name__ == "__main__":
 app = QtWidgets.QApplication(sys.argv)
 Form = QtWidgets.QWidget()
 ui = Ui_Form()
 ui.setupUi(Form)
 Form.show()
 sys.exit(app.exec_())

4.运行结果截图

Python实现LR1文法的完整实例代码
Python实现LR1文法的完整实例代码

5.学会自己看注释

6.用数据代码,为我爱的世界添砖加瓦

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

Python 相关文章推荐
用Python进行行为驱动开发的入门教程
Apr 23 Python
python 实现自动远程登陆scp文件实例代码
Mar 13 Python
python 文件转成16进制数组的实例
Jul 09 Python
分享Python切分字符串的一个不错方法
Dec 14 Python
python实现在遍历列表时,直接对dict元素增加字段的方法
Jan 15 Python
谈谈Python中的while循环语句
Mar 10 Python
Python在cmd上打印彩色文字实现过程详解
Aug 07 Python
使用turtle绘制五角星、分形树
Oct 06 Python
使用python模拟高斯分布例子
Dec 09 Python
PyCharm 无法 import pandas 程序卡住的解决方式
Mar 09 Python
Python文件操作及内置函数flush原理解析
Oct 13 Python
python 如何在list中找Topk的数值和索引
May 20 Python
Python操作word文档插入图片和表格的实例演示
Oct 25 #Python
python时间time模块处理大全
Oct 25 #Python
使用AJAX和Django获取数据的方法实例
Oct 25 #Python
Python Tkinter实例——模拟掷骰子
Oct 24 #Python
Python+OpenCV图像处理——图像二值化的实现
Oct 24 #Python
python 下划线的不同用法
Oct 24 #Python
python 写一个性能测试工具(一)
Oct 24 #Python
You might like
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
浅谈PHP中foreach/in_array的使用
2015/11/02 PHP
thinkphp中的url跳转用法分析
2016/07/12 PHP
使用 laravel sms 构建短信验证码发送校验功能
2017/11/06 PHP
yii 框架实现按天,月,年,自定义时间段统计数据的方法分析
2020/04/04 PHP
判断脚本加载是否完成的方法
2009/05/26 Javascript
javascript 浏览器判断 绑定事件 arguments 转换数组 数组遍历
2009/07/06 Javascript
JavaScript立即执行函数的三种不同写法
2014/09/05 Javascript
浅谈javascript 迭代方法
2015/01/21 Javascript
Angularjs使用ng-repeat中$even和$odd属性的注意事项
2016/12/31 Javascript
详解Vue 事件修饰符capture 的使用
2017/12/29 Javascript
详解Vue的watch中的immediate与watch是什么意思
2019/12/30 Javascript
[05:22]DOTA2 2015国际邀请赛中国区预选赛首日TOP10
2015/05/26 DOTA
[01:45]典藏宝瓶2+祈求者身心——这就是DOTA2TI9总奖金突破3000万美元的秘密
2019/07/21 DOTA
Python批量创建迅雷任务及创建多个文件
2016/02/13 Python
Python 装饰器深入理解
2017/03/16 Python
详解Python里使用正则表达式的ASCII模式
2017/11/02 Python
django自带的server 让外网主机访问方法
2018/05/14 Python
python提取具有某种特定字符串的行数据方法
2018/12/11 Python
使用python的pandas为你的股票绘制趋势图
2019/06/26 Python
哈工大自然语言处理工具箱之ltp在windows10下的安装使用教程
2020/05/07 Python
Python+PyQt5实现灭霸响指功能
2020/05/25 Python
PyTorch: Softmax多分类实战操作
2020/07/07 Python
Python自动化测试基础必备知识点总结
2021/02/07 Python
button在IE6/7下的黑边去除方案
2012/12/24 HTML / CSS
个人收入证明范本
2014/01/12 职场文书
2014年计算机专业个人自我评价
2014/01/19 职场文书
争先创优活动总结
2014/08/27 职场文书
公司离职证明样本
2014/09/13 职场文书
离婚协议书应该怎么写
2014/10/12 职场文书
留学推荐信怎么写
2015/03/26 职场文书
2015年幼儿园卫生保健工作总结
2015/05/12 职场文书
搭讪开场白台词大全
2015/05/28 职场文书
PL350与SW11的比较
2021/04/22 无线电
一篇文章弄清楚Ajax请求的五个步骤
2022/03/17 Javascript
MySQL创建管理KEY分区
2022/04/13 MySQL