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

python實(shí)現(xiàn)文法左遞歸的消除方法

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

前言

  • 繼詞法分析后,又來(lái)到語(yǔ)法分析范疇。完成語(yǔ)法分析需要解決幾個(gè)子問(wèn)題,今天就完成文法左遞歸的消除。
  • 沒(méi)借鑒任何博客,完全自己造輪子。

開(kāi)始之前

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

要求

  • 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)
#轉(zhuǎn)換坐標(biāo)顯示形式為元組
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')
    '''
    加上會(huì)判斷輸出非遞歸產(chǎn)生式,但會(huì)導(dǎo)致間接左遞歸不能刪除多余產(chǎn)生式
    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('|')#將含非終結(jié)與不含分開(kāi)
    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

#點(diǎn)擊按鈕后執(zhí)行的函數(shù)
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 = '出錯(cuò)了!',message='輸入不能為空'))
  else:
    for cfg in text_list:
      
      x,y = cfg.split('->')#將文法左右分開(kāi)
      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 = '出錯(cuò)了!',
        message='非上下文無(wú)關(guān)文法!坐標(biāo)%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)
#簡(jiǎn)單樣式
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()

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

文法左遞歸

直接左遞歸

直接左遞歸

間接左遞歸合并

間接左遞歸合并

運(yùn)行截圖

報(bào)錯(cuò)
左遞歸消除

總結(jié)

(1)確定方向

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

(2)開(kāi)始實(shí)現(xiàn)

首先將消除左遞歸的方法理解透徹,找到了程序的本質(zhì)就是對(duì)字符串的操作。
完成直接左遞歸算法非常順利,我思路嚴(yán)謹(jǐn)步步為營(yíng),幾乎沒(méi)有bug,后續(xù)測(cè)試僅僅加上一些邊緣情況的判斷,比如空值,讓程序面對(duì)復(fù)雜產(chǎn)生式也游刃有余。
將間接左遞歸的產(chǎn)生式合并的算法也很順利,因?yàn)槲以诓莞寮埳弦呀?jīng)勾勒好了每一步需要得到什么,寫代碼時(shí),一步一個(gè)輸出,看是否符合預(yù)期,后續(xù)測(cè)試稍微小補(bǔ)增強(qiáng)健壯性。真正難點(diǎn)在于構(gòu)思思路,就連最外層兩個(gè)迭代都考慮了很久。
這兩個(gè)算法的邏輯和思路是很復(fù)雜的,字符串的分分合合,分別存儲(chǔ),使用列表和字符串?dāng)?shù)據(jù)類型不下十個(gè),再加上幾個(gè)全局變量,我對(duì)自己清晰的思路略感自豪。

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

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

相關(guān)文章

  • python離散建模之感知器學(xué)習(xí)算法

    python離散建模之感知器學(xué)習(xí)算法

    這篇文章主要介紹了python離散建模之感知器學(xué)習(xí)算法,感知機(jī)學(xué)習(xí)算法是支持向量機(jī)的基礎(chǔ),支持向量機(jī)通過(guò)核函數(shù)進(jìn)行非線性分類,支持向量機(jī)也是感知機(jī)算法的延伸,下面就來(lái)介紹感知算法的相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-02-02
  • Python使用FTP上傳文件的實(shí)現(xiàn)示例

    Python使用FTP上傳文件的實(shí)現(xiàn)示例

    本文主要介紹了Python使用FTP上傳文件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Python+kivy BoxLayout布局示例代碼詳解

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

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

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

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

    Python實(shí)現(xiàn)TOPSIS分析法的示例代碼

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

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

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

    Python 占位符的使用方法詳解

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

    Python中的Networkx的基本使用

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

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

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

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

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

最新評(píng)論

富顺县| 衡阳县| 沈阳市| 唐海县| 武冈市| 通海县| 三都| 乐山市| 双鸭山市| 庄河市| 大田县| 都兰县| 桐柏县| 玉山县| 珠海市| 雷波县| 措美县| 五家渠市| 平遥县| 克东县| 朝阳区| 应用必备| 镇宁| 奉节县| 宝兴县| 浠水县| 蒙阴县| 浦东新区| 佛冈县| 奉贤区| 定边县| 高邑县| 光山县| 泽库县| 交口县| 仙桃市| 石景山区| 南康市| 偏关县| 青田县| 文化|