青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-341  評論-2670  文章-0  trackbacks-0

上一篇博客寫到了如何給一個非終結(jié)符的文法規(guī)則構(gòu)造出一個壓縮過的下推狀態(tài)機(jī),那么今天說的就是如何把所有的文法都連接起來。其實主要的idea在(三)和他的勘誤(三點五)里面已經(jīng)說得差不多了。但是今天我們要處理的是帶信息的transition,所以還有一些地方要注意一下。

所以在這里我們先把幾條文法的最后的狀態(tài)機(jī)都列出來(大圖):

image

接下來的這一步,就是要對所有靠非終結(jié)符(Exp啊Term這些)進(jìn)行跳轉(zhuǎn)的transition都執(zhí)行上一篇文章所說的傳說中的交叉鏈接。在產(chǎn)生鏈接的時候,我們給shift和reduce的邊分別加上shift和reduce。而shift和reduce是有參數(shù)的——就是被shift走的狀態(tài)的id。這樣可以在parse的時候匹配和處理狀態(tài)堆棧。在這里我門對e3->e1這一步做一下操作做為例子。紅色的邊是被刪掉的,而粗壯的綠色邊是被新加進(jìn)去的:

image

紅色的邊變成了兩條綠色的邊,紅色的邊附帶的信息則被復(fù)制到了綠色的reduce邊上。當(dāng)我們使用這個狀態(tài)機(jī)的時候,shift(s3)就表示往堆棧里面壓入s3,reduce(s3)就表示從堆棧里面彈出(s3)。當(dāng)然彈出不一定會成功,所以如果不成功的話,這條邊就不能在當(dāng)時使用。因此這也就是為什么在e3跳轉(zhuǎn)到t0之后,t1知道往回跳的是e1而不是別的什么地方——就如同為什么C++的函數(shù)執(zhí)行完之后總是知道如何跳轉(zhuǎn)回調(diào)用它的地方一樣——因為把信息推入了堆棧。

那現(xiàn)在我們就來看一下,當(dāng)所有的非終結(jié)符跳轉(zhuǎn)都處理掉之后,會變成什么樣子吧(這個圖真是復(fù)雜和亂到我不想畫?。?,為了讓圖變得不那么糟糕,我把shift都變成紫色,reduce都變成綠色:

image

在添加shift和reduce邊之前,每一條邊都是有輸入token的。但是我們剛剛添加上去的shift和reduce邊卻是不輸入token的,所以他們是epsilon邊,下一步就是要消除他們。上面這個圖消除了epsilon邊之后,會變成一個狀態(tài)很少,但是每一條邊附帶的信息都會非常多,而且像n1這種經(jīng)常到達(dá)的狀態(tài)(因為四則運算里面有很多數(shù)字)將恢復(fù)射出無數(shù)條邊。到了這里這個狀態(tài)機(jī)已經(jīng)再也畫不出來了。所以我下面就只拿兩個例子來畫。下面要展示的是用Exp來parse單獨的一個數(shù)字會走的邊,當(dāng)然就是Exp –> Term –> Factor –> Number了:

image

就會被處理成:

image

注意邊上面的信息是要按順序重新疊加在一起的。當(dāng)所有的epsilon邊都去掉了之后,我們就得到了最終的一個狀態(tài)機(jī)。最重要的一件事情出現(xiàn)了。我們知道,發(fā)明LR和LALR這種東西就基本上是為了處理左遞歸的,所以這種圖就可以在去除epsilon邊的過程中自動發(fā)現(xiàn)左遞歸。這是怎么做到的呢?只要在去除epsilon邊的時候,發(fā)現(xiàn)了一條完全由shift這種epsilon邊組成的環(huán),那么左遞歸就發(fā)現(xiàn)了。為了方便,我們可以只處理直接左遞歸——就是這種環(huán)的長度是1的。不包含間接左遞歸的問法是很容易寫出來的。當(dāng)然這種環(huán)并不一定是首尾相接的,譬如說我們在處理e0的時候就會發(fā)現(xiàn)e0->t0->t0這種環(huán)(當(dāng)然嚴(yán)格來說環(huán)只有最后一截的這個部分)。我們的程序要很好地應(yīng)對這種情況。因為我們只接受直接左遞歸,所以類似這種結(jié)構(gòu)的epsilon路徑可以直接的拋棄他,因為t0->t0會被t0狀態(tài)單獨處理掉。因此這樣做并不會漏掉什么。

細(xì)心的朋友可能會發(fā)現(xiàn),這個結(jié)構(gòu)的圖是不能直接處理右遞歸的(總之左遞歸和右遞歸總要有一個會讓你的狀態(tài)機(jī)傻逼就是了?。?。關(guān)于如何處理有遞歸(其實內(nèi)容也不復(fù)雜)地方法會在“下篇”描述出來。那處理左遞歸有什么用呢?舉個例子,我們的e0->e2就是一個左遞歸,而他會在之前的步驟被處理成shift(e0->e0)和reduce(e1->e2)。我們要記下shift和reduce的對應(yīng)關(guān)系,那么當(dāng)我們找到一個左遞歸的shift之后,我們就可以把對應(yīng)的reduce給標(biāo)記成“left-recursive-reduce”。這是一個在構(gòu)造語法樹的時候,非常關(guān)鍵的一種構(gòu)造指令。

處理完這些之后,我們可以把左遞歸的shift邊全部刪掉,最后把token和state都統(tǒng)統(tǒng)處理成連續(xù)的數(shù)字,做成一張[state, token] –> [transitions]的二維表,每一個表的元素是transition的列表。為什么是這樣呢?因為我們對一個state輸入一個token之后,由于保存著state的堆棧(你還記得嗎?shift==push,reduce==pop)的棧頂若干個元素的不同,可能會走不通的路線。于是最后我們就得到了這么一張圖。

下面這張圖可以通過運行g(shù)ac.codeplex.com上面的Common\UnitTest\UnitTest.sln(VS2012限定)之后,在Common\UnitTest\TestFiles\Parsing.Calculator.Table.txt里面找到。這一組文件都是我在測試狀態(tài)機(jī)的時候log下來的。

image

如果大家有VS2012的話,通過運行我準(zhǔn)備的幾個輸入,譬如說“1*2+3*4”,就可以在Parsing.Calculator.[2].txt里面找到所有狀態(tài)跳轉(zhuǎn)的軌跡。因為我們總是需要parse一個Exp,所以我們從22: Exp.RootStart開始。我們假設(shè)token stream的第一個和最后一個分別是$TokenBegin和$TokenFinish。上圖的$TryReduce是為了應(yīng)對右遞歸而設(shè)計出來的一種特殊輸入。由于四則運算里面并沒有右遞歸,所以這一列就是空的:

StartState: 22[Exp.RootStart]
$TokenBegin => 23[Exp.Start]
    State Stack:
NUMBER[1] => 2[Number.1]
    State Stack: 23[Exp.Start], 21[Term.Start], 19[Factor.Start]
    Shift 23[Exp]
    Shift 21[Term]
    Shift 19[Factor]
    Assign value
    Create NumberExpression
MUL[*] => 5[Term.3]
    State Stack: 23[Exp.Start]
    Reduce 19[Factor]
    Using
    Reduce 21[Term]
    Using
    LR-Reduce 21[Term]
    Assign firstOperand
    Setter binaryOperator = Mul
    Create BinaryExpression
NUMBER[2] => 2[Number.1]
    State Stack: 23[Exp.Start], 5[Term.3], 19[Factor.Start]
    Shift 5[Term]
    Shift 19[Factor]
    Assign value
    Create NumberExpression
ADD[+] => 10[Exp.3]
    State Stack:
    Reduce 19[Factor]
    Using
    Reduce 5[Term]
    Assign secondOperand
    Reduce 23[Exp]
    Using
    LR-Reduce 23[Exp]
    Assign firstOperand
    Setter binaryOperator = Add
    Create BinaryExpression
NUMBER[3] => 2[Number.1]
    State Stack: 10[Exp.3], 21[Term.Start], 19[Factor.Start]
    Shift 10[Exp]
    Shift 21[Term]
    Shift 19[Factor]
    Assign value
    Create NumberExpression
MUL[*] => 5[Term.3]
    State Stack: 10[Exp.3]
    Reduce 19[Factor]
    Using
    Reduce 21[Term]
    Using
    LR-Reduce 21[Term]
    Assign firstOperand
    Setter binaryOperator = Mul
    Create BinaryExpression
NUMBER[4] => 2[Number.1]
    State Stack: 10[Exp.3], 5[Term.3], 19[Factor.Start]
    Shift 5[Term]
    Shift 19[Factor]
    Assign value
    Create NumberExpression
$TokenFinish => 11[Exp.RootEnd]
    State Stack:
    Reduce 19[Factor]
    Using
    Reduce 5[Term]
    Assign secondOperand
    Reduce 10[Exp]
    Assign secondOperand

我們把所有跳轉(zhuǎn)過的transition的信息都記錄下來,就可以構(gòu)造語法蘇了。我們想象一下,在執(zhí)行這些指令的時候,遇到NUMBER[4]就等于獲得了一個內(nèi)容為4的token,shift的話就是往堆棧里面push進(jìn)一個狀態(tài)的名字,而reduce則是彈出。

相對應(yīng)的,因為每一個文法都會創(chuàng)建一個對象,所以我們在初始化的時候,要先放一個空對象在堆棧上。shift一次就再創(chuàng)建一個空的對象push進(jìn)去,reduce的時候就把棧頂?shù)膶ο髲棾鰜碜鳛?#8220;待處理對象”,using了就把待處理對象和棧頂對象合并,left-reduce就是把棧頂對象彈出來作為待處理對象的同時,push一個空對象進(jìn)去。assign fieldName就是把“待處理對象”保存到棧頂對象的叫做fieldName的成員變量里面去。如果棧頂對象為空,那么被保存的對象就是剛剛輸入的那個token了。因此我們從頭到尾執(zhí)行一遍之后,就可以得到下面的一顆語法樹:

BinaryExpression {
    binaryOperator = [Add]
    firstOperand = BinaryExpression {
        binaryOperator = [Mul]
        firstOperand = NumberExpression {
            value = [1]
        }
        secondOperand = NumberExpression {
            value = [2]
        }
    }
    secondOperand = BinaryExpression {
        binaryOperator = [Mul]
        firstOperand = NumberExpression {
            value = [3]
        }
        secondOperand = NumberExpression {
            value = [4]
        }
    }
}

基本上parsing的過程就結(jié)束了。在“下篇”——也就是(六)——里面,我會講述如何處理右遞歸,然后這個系列基本上就要完結(jié)了。

posted on 2012-12-31 23:52 陳梓瀚(vczh) 閱讀(4756) 評論(10)  編輯 收藏 引用 所屬分類: C++

評論:
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-01 18:58 | ooseven
LL自動機(jī)有對左遞歸文法的限制
LR與LALR有對右遞歸文法的限制

一般的語法自動機(jī)都是要求用戶在文法上手動進(jìn)行轉(zhuǎn)換,而且轉(zhuǎn)換很簡單,如果設(shè)計成在自動機(jī)里自動轉(zhuǎn)換很麻煩而且難度不小,你的自動機(jī)是設(shè)計成如果發(fā)現(xiàn)用戶的文法是右遞歸的就自動轉(zhuǎn)換的嗎?
  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-01 19:49 | 陳梓瀚(vczh)
@ooseven
如果實在找不到合適的transition,就會尋找一個右遞歸reduce試試看。因為在任何時候合適的右遞歸reduce只有一個,而且只有直接或者間接指向右遞歸文法的文法的終結(jié)狀態(tài)有右遞歸reduce,所以這是正確的跳轉(zhuǎn)。所以你看我把右遞歸的input叫TryReduce,而且他是不吃token的。這里面不會發(fā)生歧義。

所以其實我一直都在用LR的模型,只是稍微修改了一下,加入了右遞歸的支持。  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-02 05:52 | mario
題外話,樓主用的是什么畫圖工具啊~。  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-02 10:42 | 陳梓瀚(vczh)
@mario
PowerPoint   回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-10 21:40 | Scan
老大,有一件事:你能不能轉(zhuǎn)開一篇文章介紹好書?。?!比如,置頂?shù)摹禤arsing Techniques》和上次的《編程語言實現(xiàn)模式》。
如果嫌給新人介紹入門書太麻煩什么的,可以直接講一下各個領(lǐng)域你看得上眼的好書啊!非常有參考價值!  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-12 05:26 | 陳梓瀚(vczh)
@Scan
這個你直接入群來問就行啦,啊哈哈哈哈  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-12 08:43 | Scan
@陳梓瀚(vczh)
在里面的,總覺的群里說話太隨意,不比這邊的文章質(zhì)量...算了還是先看手里的好了...
  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-14 10:03 | Scan
自頂向下語法分析不能有左遞歸,是因為,選擇產(chǎn)生式不會消耗輸入詞法單元,因此左遞歸會是不修改任何狀態(tài)的死循環(huán)。
但是在自底向上的LR語法分析中,每次規(guī)約雖然不會消耗輸入,但是會彈出狀態(tài)棧上的幾個狀態(tài)同時查表壓入新狀態(tài),哪怕是右遞歸的規(guī)約也影響了狀態(tài)機(jī)啊,右遞歸對LR分析應(yīng)該是無害的才是?  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-01-19 19:38 | 陳梓瀚(vczh)
@Scan
害表現(xiàn)在,你構(gòu)造不出完整的右遞歸的邊。  回復(fù)  更多評論
  
# re: 可配置語法分析器開發(fā)紀(jì)事(五)——構(gòu)造一個真正能用的狀態(tài)機(jī)(中) 2013-02-26 00:46 | abcd
@陳梓瀚(vczh)
怎么構(gòu)造不出完整的右遞歸的邊?舉個例子  回復(fù)  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久综合久久久久88| 亚洲午夜一级| 欧美精品v日韩精品v国产精品| 91久久综合亚洲鲁鲁五月天| 欧美v国产在线一区二区三区| 久久久精品日韩| 在线综合亚洲| 欧美精品999| 亚洲电影在线看| 国产欧美韩日| 亚洲精品乱码视频| 一区二区三区在线不卡| 亚洲图片欧洲图片日韩av| 国产一区清纯| 在线一区二区日韩| 国产精品99久久久久久久久久久久 | 激情综合久久| 久久久久久久久一区二区| 亚洲资源在线观看| 欧美在线网址| 国产日韩欧美在线播放不卡| 夜夜嗨av一区二区三区免费区| 亚洲成色www久久网站| 亚洲欧洲99久久| 欧美一区二区精美| 国产一区二区在线观看免费播放| 亚洲欧美日韩成人| 午夜欧美不卡精品aaaaa| 国产精品专区h在线观看| 亚洲小视频在线| 久久噜噜亚洲综合| 亚洲第一在线综合在线| 欧美+亚洲+精品+三区| 亚洲一级二级在线| 亚洲第一在线视频| 亚洲欧美怡红院| 夜夜狂射影院欧美极品| 伊人久久婷婷| 国产免费观看久久| 欧美日韩在线免费观看| 欧美成人综合在线| 亚洲国产三级网| 国产日韩精品视频一区二区三区 | 亚洲高清在线播放| 国产精品日韩二区| 你懂的视频一区二区| 亚洲一区国产视频| 欧美成人精品福利| 久久色在线播放| 亚洲欧美日韩视频二区| 91久久精品国产91久久| 极品少妇一区二区三区精品视频| 欧美激情亚洲自拍| 麻豆精品一区二区av白丝在线| 亚洲小说欧美另类社区| 欧美福利精品| 欧美日韩另类字幕中文| 久久精品国产一区二区三区免费看 | 一区二区动漫| 亚洲精品四区| 一本一本久久| 欧美一区二粉嫩精品国产一线天| 亚洲一区二区3| 亚洲一区二区三区中文字幕| 亚洲影视综合| 老牛国产精品一区的观看方式| 欧美激情视频免费观看| 久久久精品999| 国产亚洲午夜高清国产拍精品| 国产精品久久国产精品99gif | 亚洲精品老司机| 影音先锋日韩精品| 在线电影国产精品| 99在线精品视频| 美女性感视频久久久| 欧美国产日本在线| 一区二区三区国产| 久久久精品一品道一区| 欧美激情91| 伊人色综合久久天天| 一区二区久久| 亚洲欧美日韩一区在线| 亚洲国产日韩欧美| 亚洲综合色自拍一区| 国产精品久久久久久久久免费| 日韩视频一区二区在线观看 | 午夜精品偷拍| 亚洲国产精品专区久久| 老司机一区二区| 欧美激情区在线播放| 免费中文字幕日韩欧美| 亚洲黄色在线视频| 亚洲三级视频| 国产一区二区精品在线观看| 欧美视频精品在线观看| 亚洲免费人成在线视频观看| 亚洲一区二区三区视频播放| 欧美日韩一区二区免费视频| 洋洋av久久久久久久一区| 亚洲乱码国产乱码精品精可以看| 欧美r片在线| 中国女人久久久| 亚洲婷婷综合久久一本伊一区| 国产精品乱子久久久久| 性做久久久久久免费观看欧美| 亚洲午夜精品久久久久久app| 国产毛片精品国产一区二区三区| 久久国产精品久久久久久| 久久久国产精品一区| aa亚洲婷婷| 欧美一区二区三区视频| 亚洲丁香婷深爱综合| 日韩亚洲欧美精品| 国产香蕉97碰碰久久人人| 欧美激情按摩在线| 国产精品视频专区| 亚洲日韩视频| 亚洲电影有码| 亚洲影视中文字幕| 亚洲国产一区在线| 久久国产精品99国产精| 欧美中文字幕| 国产亚洲一区二区三区在线观看| 日韩一级在线观看| 中国成人黄色视屏| 欧美日韩亚洲另类| 欧美激情亚洲一区| 好看不卡的中文字幕| 亚洲午夜极品| aaa亚洲精品一二三区| 久久久久国色av免费观看性色| 午夜日本精品| 国产精品自在在线| 欧美一区二区性| 久久久久九九视频| 国产一区自拍视频| 久久久91精品国产一区二区精品| 久久精品国产一区二区电影| 国产欧美日韩一级| 久久精品国产亚洲高清剧情介绍| 性做久久久久久久久| 国产一区二三区| 欧美激情一区二区三级高清视频| 亚洲欧洲一区二区在线播放| 免费短视频成人日韩| 日韩视频在线观看一区二区| 午夜日韩电影| 亚洲午夜激情免费视频| 在线观看亚洲精品| 国产精品美女久久久久久免费 | 亚洲第一精品影视| 欧美在线播放高清精品| 日韩视频在线永久播放| 伊人狠狠色丁香综合尤物| 国产精品v欧美精品v日韩精品| 欧美成人精品高清在线播放| 欧美专区日韩专区| 亚洲午夜一级| 亚洲午夜在线观看| 久久伊人亚洲| 亚洲一区精品电影| 国产曰批免费观看久久久| 欧美日韩福利在线观看| 久久超碰97中文字幕| aa级大片欧美| 亚洲国产成人一区| 久久精品在线视频| 午夜精品久久久久久久蜜桃app| 亚洲精品乱码久久久久久按摩观| 国产欧美日韩在线视频| 欧美日韩成人在线观看| 欧美国产日韩一区二区| 麻豆精品视频| 久久久久久穴| 美女网站在线免费欧美精品| 久久精彩免费视频| 久久国产一区二区| 久久久精彩视频| 久久欧美肥婆一二区| 久久午夜精品一区二区| 久久精品视频亚洲| 久久国内精品视频| 久久久久久网站| 欧美大学生性色视频| 欧美日韩免费在线观看| 国产精品乱码一区二区三区| 欧美性大战久久久久久久| 国产精品老牛| 亚洲精品国产精品国产自| 一级日韩一区在线观看| 亚洲永久免费| 美女91精品| 在线观看中文字幕不卡| 99精品欧美一区二区三区综合在线| 亚洲黄页一区| 欧美一区深夜视频| 欧美国产一区二区三区激情无套| 99精品国产99久久久久久福利| 亚洲一区二区三区高清| 久久在线视频在线|