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

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

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

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

image

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

image

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

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

image

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

image

就會被處理成:

image

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

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

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

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

image

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

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

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

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

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

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

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

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

所以其實我一直都在用LR的模型,只是稍微修改了一下,加入了右遞歸的支持。  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-02 05:52 | mario
題外話,樓主用的是什么畫圖工具啊~。  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-02 10:42 | 陳梓瀚(vczh)
@mario
PowerPoint   回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-10 21:40 | Scan
老大,有一件事:你能不能轉開一篇文章介紹好書啊!!比如,置頂的《Parsing Techniques》和上次的《編程語言實現模式》。
如果嫌給新人介紹入門書太麻煩什么的,可以直接講一下各個領域你看得上眼的好書啊!非常有參考價值!  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-12 05:26 | 陳梓瀚(vczh)
@Scan
這個你直接入群來問就行啦,啊哈哈哈哈  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-12 08:43 | Scan
@陳梓瀚(vczh)
在里面的,總覺的群里說話太隨意,不比這邊的文章質量...算了還是先看手里的好了...
  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-14 10:03 | Scan
自頂向下語法分析不能有左遞歸,是因為,選擇產生式不會消耗輸入詞法單元,因此左遞歸會是不修改任何狀態的死循環。
但是在自底向上的LR語法分析中,每次規約雖然不會消耗輸入,但是會彈出狀態棧上的幾個狀態同時查表壓入新狀態,哪怕是右遞歸的規約也影響了狀態機啊,右遞歸對LR分析應該是無害的才是?  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-01-19 19:38 | 陳梓瀚(vczh)
@Scan
害表現在,你構造不出完整的右遞歸的邊。  回復  更多評論
  
# re: 可配置語法分析器開發紀事(五)——構造一個真正能用的狀態機(中) 2013-02-26 00:46 | abcd
@陳梓瀚(vczh)
怎么構造不出完整的右遞歸的邊?舉個例子  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲电影在线观看| 欧美 亚欧 日韩视频在线| 欧美天堂亚洲电影院在线观看 | 欧美一区二区三区视频| 亚洲精品乱码久久久久久| 欧美freesex交免费视频| 亚洲人成人一区二区在线观看| 欧美bbbxxxxx| 国产精品国产一区二区 | 亚洲国产日韩欧美一区二区三区| 久久成人亚洲| 久久久人成影片一区二区三区 | 乱中年女人伦av一区二区| 久久精品国产99国产精品澳门| 国产一区二区三区高清播放| 久久国产福利国产秒拍| 欧美日韩精品免费在线观看视频| 香蕉成人啪国产精品视频综合网| 性亚洲最疯狂xxxx高清| 一区二区免费看| 久久亚洲一区二区| 久久久久久香蕉网| 国产精品视频第一区| 免费短视频成人日韩| 欧美视频国产精品| 老司机aⅴ在线精品导航| 国产精品欧美一区二区三区奶水| 91久久精品网| 亚洲午夜精品一区二区三区他趣| 免费看成人av| 亚洲国产一区二区三区青草影视| 国产麻豆视频精品| 午夜日韩激情| 久久国产日韩| 好吊日精品视频| 亚洲在线播放电影| 欧美三日本三级三级在线播放| 蜜臀久久久99精品久久久久久| 国产夜色精品一区二区av| 亚洲自拍16p| 久久久国产视频91| 伊人春色精品| 欧美大片免费| 亚洲欧美日本伦理| 免费在线国产精品| 亚洲激情视频| 国产精品激情电影| 亚洲免费一区二区| 久久中文字幕一区| 亚洲午夜高清视频| 国产日产欧美精品| 欧美极品欧美精品欧美视频| 亚洲在线一区二区三区| 久久久久久久尹人综合网亚洲| 亚洲激情视频网站| 国产女主播视频一区二区| 久久久999国产| 艳女tv在线观看国产一区| 午夜免费久久久久| 亚洲丝袜av一区| 亚洲经典自拍| 亚洲欧洲精品一区二区三区| 激情亚洲成人| 国产亚洲免费的视频看| 欧美精品国产一区二区| 久久天堂精品| 另类av导航| 欧美在线视频观看免费网站| 亚洲激情第一页| 亚洲黄色在线观看| 亚洲激情综合| 91久久国产综合久久| 欧美国产日韩在线| 久久久久成人精品| 国产精品爱久久久久久久| 裸体一区二区| 夜夜夜久久久| 午夜免费在线观看精品视频| 欧美一区日韩一区| 老司机免费视频久久| 欧美国产日韩一区| 欧美日韩国产首页| 午夜在线成人av| 免费h精品视频在线播放| 欧美福利专区| 一区二区三区www| 一本色道久久综合亚洲91| 欧美中文日韩| 欧美涩涩视频| 影音先锋久久精品| 香蕉久久夜色精品国产使用方法| 久久久久一区二区三区| 最新亚洲激情| 午夜精品www| 欧美人与性禽动交情品 | 国产精品美女www爽爽爽| 国产精品一区二区男女羞羞无遮挡| 欧美日韩午夜精品| 亚洲激情小视频| 免费成人高清| 亚洲久久一区| 欧美日韩国产色视频| 国产精品久久久久久久久免费 | 亚洲精品一区二区在线观看| 久久久精品国产免大香伊| 国产目拍亚洲精品99久久精品| 亚洲国产高清视频| 久久国产精品久久久| 亚洲男人第一av网站| 欧美性事免费在线观看| 99视频在线精品国自产拍免费观看 | 亚洲高清二区| 欧美精品一区在线播放| 国产精品99久久99久久久二8| 欧美第一黄色网| 欧美极品一区二区三区| 亚洲国产高清在线观看视频| 久久精品中文| 久久米奇亚洲| 亚洲午夜久久久久久久久电影院| 一区二区三区精密机械公司 | 亚洲精品视频在线播放| 欧美日韩不卡合集视频| 亚洲欧美日韩综合国产aⅴ| 亚洲一区二区三区中文字幕| 国产精品一区二区黑丝| 狼人社综合社区| 欧美日韩精品三区| 欧美中文字幕在线| 久久久综合激的五月天| 日韩视频一区二区三区在线播放| 亚洲经典视频在线观看| 国产精品久久一卡二卡| 欧美护士18xxxxhd| 国语对白精品一区二区| 亚洲精品中文字幕女同| 国产欧美亚洲视频| 欧美丰满高潮xxxx喷水动漫| 狠狠入ady亚洲精品| 亚洲小说春色综合另类电影| 亚洲国产欧美一区| 久久久爽爽爽美女图片| 午夜精品国产精品大乳美女| 久久免费高清| 欧美国产亚洲另类动漫| 亚洲日本中文字幕免费在线不卡| 亚洲少妇在线| 一区二区三区四区五区视频| 久久精品视频一| 玖玖视频精品| 亚洲国产欧美一区二区三区丁香婷| 亚洲网站在线看| 蜜桃久久av一区| 欧美成人资源| 亚洲精品久久久久久久久久久久| 久久久久国产免费免费| 亚洲精品日韩在线观看| 午夜国产一区| 欧美大片免费| 亚洲视频在线看| 国产亚洲aⅴaaaaaa毛片| 久久成人精品电影| 亚洲国产精品高清久久久| 一本久久a久久免费精品不卡| 欧美日韩一区二区三区视频| 亚洲视频在线观看| 欧美大香线蕉线伊人久久国产精品| 亚洲国产精品久久久久秋霞影院| 欧美精品一区二区久久婷婷| 亚洲一区999| 亚洲国产日韩一级| 久久精品国产99国产精品| 亚洲日本欧美| 国产午夜精品久久| 欧美午夜精品久久久久久人妖| 亚洲欧美视频一区| 亚洲免费成人av| 亚洲第一区在线| 欧美一区二区在线| 亚洲欧洲日韩综合二区| 欧美高清视频免费观看| 中文欧美在线视频| 亚洲午夜激情免费视频| 久久国产一二区| 久久久噜噜噜久久| aa国产精品| 99在线精品视频在线观看| 最新高清无码专区| **欧美日韩vr在线| 亚洲人成网站精品片在线观看| 亚洲国产精品久久久久婷婷老年| 国内免费精品永久在线视频| 国产一区美女| 亚洲人成网站999久久久综合| 亚洲精品网址在线观看| 夜夜爽www精品| 久久国产99| 欧美不卡视频一区发布| 亚洲视频在线一区观看| 性欧美xxxx视频在线观看|