最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python實現文法左遞歸的消除方法

 更新時間:2020年05月22日 10:39:14   作者:我是注釋  
這篇文章主要介紹了python實現文法左遞歸的消除的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

前言

  • 繼詞法分析后,又來到語法分析范疇。完成語法分析需要解決幾個子問題,今天就完成文法左遞歸的消除。
  • 沒借鑒任何博客,完全自己造輪子。

開始之前

  • 文法左遞歸消除程序的核心是對字符串的處理,輸入的產生式作為字符串,對它的拆分、替換與合并操作貫穿始終,處理過程的邏輯和思路稍有錯漏便會漏洞百出。
  • 采用直接改寫法,不理解左遞歸消除方法很難讀懂代碼。

要求

  • 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

#點擊按鈕后執(zhí)行的函數
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')  

    
#創(chuàng)建文本輸入框和按鈕
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()

是不是很難懂,看看半吊子流程圖主要流程

文法左遞歸

直接左遞歸

直接左遞歸

間接左遞歸合并

間接左遞歸合并

運行截圖

報錯
左遞歸消除

總結

(1)確定方向

做一件事并不難,最難的是沒有方向,不知道要做什么;只是感覺時光流逝自己卻一點東西都沒產出。幸好有具體的題目可供選擇,這一次我稍有糾結之后,果斷選擇文法左遞歸消除,說實話,我認為這個最簡單。

(2)開始實現

首先將消除左遞歸的方法理解透徹,找到了程序的本質就是對字符串的操作。
完成直接左遞歸算法非常順利,我思路嚴謹步步為營,幾乎沒有bug,后續(xù)測試僅僅加上一些邊緣情況的判斷,比如空值,讓程序面對復雜產生式也游刃有余。
將間接左遞歸的產生式合并的算法也很順利,因為我在草稿紙上已經勾勒好了每一步需要得到什么,寫代碼時,一步一個輸出,看是否符合預期,后續(xù)測試稍微小補增強健壯性。真正難點在于構思思路,就連最外層兩個迭代都考慮了很久。
這兩個算法的邏輯和思路是很復雜的,字符串的分分合合,分別存儲,使用列表和字符串數據類型不下十個,再加上幾個全局變量,我對自己清晰的思路略感自豪。

(3)不足之處
1、我希望能夠實現,非左遞歸文法,左遞歸和間接左遞歸的一起輸入一起識別一起消除,碰到非左遞歸文法就輸出“非左遞歸文法”,然后將其不做任何修改輸出。如果實現這個,如何讓間接左遞歸不被當做非左遞歸文法處理呢?我沒想到解決方案。
2、我對非終結符的判斷采用的是是否包含,沒有更進一步判斷位置,比如消除 D -> Dh|sD|h,D在s后,這就不能很好的處理。
3、對于間接左遞歸文法產生式的輸入順序是有要求的,還沒能做到隨意輸入。
(4)遇到的問題
我遇到的問題都是關于整體結構和取舍妥協(xié),比如我最終選擇將輸入使用兩個循環(huán),一個是對一個個產生式進行迭代,消除直接左遞歸,第二個再從頭采用下標嵌套兩層循環(huán)來合并間接左遞歸。
在解決不足之處1時,我花了不少時間,用盡了方法,比如全局變量,集合,甚至還將代碼備份,進行較大改動,最后還是妥協(xié)了。
在寫兩個核心算法的時候,我每一步拿到什么數據類型,拿到什么內容,都很小心的確認,一步一步推進,沒出現“bug找一天”的情況。每到一步需要一個新的變量存儲,我就在方法最開始加一個,tihuan()這個方法就有六個變量,現在想來,空間復雜度挺高。
(5)總結
這次的設計完全自主,沒有借鑒任何博客,我也知道可能有些我認為很難的東西在大牛面前都不值一提,或許程序整體架構就差之甚遠。無論如何,題目要求的東西我做到了,而且花的時間不算長,還是挺有成就感。但是,我絕對不會驕傲,根本沒有驕傲的資本。
從畫出界面,接收文本輸入,取到產生式,判斷類型,消除直接左遞歸,合并間接左遞歸再到消除間接左遞歸。有條有理,一步一個腳印,方能萬丈高樓平地起。

到此這篇關于python實現文法左遞歸的消除方法的文章就介紹到這了,更多相關python文法左遞歸消除內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • python離散建模之感知器學習算法

    python離散建模之感知器學習算法

    這篇文章主要介紹了python離散建模之感知器學習算法,感知機學習算法是支持向量機的基礎,支持向量機通過核函數進行非線性分類,支持向量機也是感知機算法的延伸,下面就來介紹感知算法的相關內容,需要的小伙伴可以參考一下
    2022-02-02
  • Python使用FTP上傳文件的實現示例

    Python使用FTP上傳文件的實現示例

    本文主要介紹了Python使用FTP上傳文件的實現示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • Python+kivy BoxLayout布局示例代碼詳解

    Python+kivy BoxLayout布局示例代碼詳解

    這篇文章主要介紹了Python+kivy BoxLayout布局的示例代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 初探Python元編程之理解并使用元編程改變代碼的代碼示例

    初探Python元編程之理解并使用元編程改變代碼的代碼示例

    在Python編程中,有一種強大的技術允許我們在運行時修改或生成代碼,這就是元編程,Python的元編程工具包括裝飾器,元類,以及函數和類的各種動態(tài)修改技術,這篇文章將向你介紹元編程的基本概念,并通過實例講解如何使用元編程
    2023-07-07
  • Python實現TOPSIS分析法的示例代碼

    Python實現TOPSIS分析法的示例代碼

    TOPSIS法是一種常用的綜合評價方法,其能充分利用原始數據的信息,其結果能精確反應各評價方案之間的差距。本文將利用Python實現這一方法,感興趣的可以了解一下
    2023-02-02
  • python中判斷文件編碼的chardet(實例講解)

    python中判斷文件編碼的chardet(實例講解)

    下面小編就為大家分享一篇python中判斷文件編碼的chardet(實例講解),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • Python 占位符的使用方法詳解

    Python 占位符的使用方法詳解

    這篇文章主要介紹了Python 占位符的使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • Python中的Networkx的基本使用

    Python中的Networkx的基本使用

    Networkx是一個Python的包,可以用來創(chuàng)建和處理復雜的圖網絡結構,這篇文章主要介紹了Python中的Networkx詳解,需要的朋友可以參考下
    2023-02-02
  • 解析python 類方法、對象方法、靜態(tài)方法

    解析python 類方法、對象方法、靜態(tài)方法

    這篇文章主要介紹了解析python 類方法、對象方法、靜態(tài)方法的的相關資料,幫助大家更好的理解和學習python,感興趣的朋友可以了解下
    2020-08-08
  • Python文件循環(huán)寫入行時防止覆蓋的解決方法

    Python文件循環(huán)寫入行時防止覆蓋的解決方法

    今天小編就為大家分享一篇Python文件循環(huán)寫入行時防止覆蓋的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11

最新評論

合肥市| 阿克苏市| 武陟县| 大邑县| 霍州市| 怀化市| 丽江市| 邻水| 合阳县| 富顺县| 甘孜| 旬邑县| 邹平县| 遂平县| 沙洋县| 南安市| 呼玛县| 全州县| 上杭县| 临高县| 恭城| 凤凰县| 平安县| 黎平县| 兰西县| 彰化市| 吉林市| 安阳县| 永定县| 和田市| 拜泉县| 邮箱| 厦门市| 曲阜市| 丰原市| 上犹县| 常熟市| 新密市| 寿光市| 共和县| 新和县|