C_and_CPP 板


LINE

因為有人問道,所以今天講一下 yard 背後的精神跟設計手法… 讓我們回想一下 recursive decent parser 最原始的模樣, 假設我今天想要 parse 的文法是 (ab)*xyz[cd] 那我會怎麼寫我的 parser? 大概是這樣 // ab bool ab() { char* q = p ; if ( *p++ == 'a' && *p++ == 'b' ) return true ; // 成功 p = q ; return false ; // 失敗,roll back } // xyz bool xyz() { char* q = p ; if ( *p++ == 'x' && *p++ == 'y' && *p++== 'z' ) return true ; p = q ; return false ; } // (ab)*xyz[cd] bool abab_xyz_cd() { char* q = p ; if ( abab() && xyz() && cd() ) return true ; p = q ; return false ; } 可以看得出來, 其實這些函數的架構都非常相似, 首先是保留 roll back 時需要的目前指標的位置, 然後是一個一個比對吃進來的序列,最後如果失敗就進行 roll back, 除了裡面用來比對所呼叫的函數不一樣,整個架構都是一樣的。 既然這些函數架構都一樣,除了裡面呼叫的函數不一樣, 那讓我們想到:C++ 的 template 剛剛好可以派上用場! 我們可以寫一個 function template。 template < class F0, class F1, class F2 > bool Seq () { char* q = p ; if ( F0() && F1() && F2() ) return true ; p = q ; return false ; } 於是 abab_xyz_cd() 其實可以寫成這樣… //(ab)*xyz[cd] bool Seq < abab, xyz, cd > () ; 不過這邊有兩個問題要解決,一個是小問題,另外一個比較麻煩, 小的那個問題是:如果我只想傳入兩個參數怎麼辦? 好在 C++ 的 template 支援了預設參數的功能! 我們可以設計一個函數永遠傳回 true bool True () { return true ; } 然後把我們的 Seq 改寫成 template < class F0, class F1=True, class F2=True > bool Seq () { ........ } 事情輕輕鬆鬆就解決了! 注意一下第一個參數沒有預設值, 因為當你說你要一個 "Seq" 的時候, 想當然你不會什麼東西都不給他就叫他去比對吧。 當然如果你想要實現一個不吃東西的 rule,那是另外一回事, 這邊不多說,可以自己看看 yard 的 source 是怎麼做的 :) 另外一個問題比較麻煩,讓我們回頭看一下剛剛新寫好的那個規則… //(ab)*xyz[cd] bool Seq < abab, xyz, cd > () ; 其實這東西編譯根本不會過,他看起來像是一個特化函數,但是語法也不對。 而且他沒有名字,你沒辦法重複使用這個新定義出來的函數, 沒有人會希望每次用到這個規則的時候都要重複打上整串東西。 聰明的人馬上就想到:我可以用 function pointer 阿! bool (*abab_xyz_cd)() = Seq < abab, xyz, cd > ; 媽阿,這鬼東西編譯會過嗎?會。不過事情沒這麼美好,當你想要 //(ab)*xyz[cd]gg bool (*abab_xyz_cd_gg)() = Seq < abab_xyz_cd, gg > ; 的時候你就 gg 了。 編譯器會跟你靠北一個你看不懂的錯誤訊息,不用看懂沒關係, 簡單的原因就是因為這時候 abab_xyz_cd 不是一個型別也不是函數,而是一個變數, 函數指標不是函數,是變數,而你不能把變數塞到 template 裡面當作參數, 於是你現在有辦法定義一個函數,但是你辦法復用他,等於還是沒用。 解決的方法是把這些函數 rule 用 class 包起來。 template < class F0, class F1, class F2 > class Seq { bool match() { char* q = p ; if ( F0.match() && F1.match() && F2.match() ) return true ; p = q ; return false ; } } 然後當你要定義新規則的時候,定一個 class,繼承那些泛型的 rule, class abab_xyz_cd : Seq < abab, xyz, cd > {} ; 現在一切都解決了,這些 rule 有名字,也可以被復用! 而且改寫成 class 還有另外一個好處:函數指標不能被 inline,但是 funtor 可以! 雖然我們取的名字不是 operator()(),但是效果一樣,這對執行效能有很大的提昇。 我們很接近最後的完成品了,只剩下一點點小問題,就是我們的 p 是個全域變數, 我們可以設計一個 ParseState class 把目前處理到的位置跟本文封裝起來, ParseState 的細節就不提了,我們直接看改好的 Seq 是什麼樣子…… template < class F0, class F1, class F2 > class Seq { bool match(ParseState& p) { ParseState::Iter q = p.pos() ; if ( F0.match(p) && F1.match(p) && F2.match(p) ) return true ; p.setPos(q) ; return false ; } } 終於大功告成啦… 這個是用來 match 序列的 class template, 只要明白設計理念以後,其實勝下的像是 Or, Star, Plus 或是 Repeat 都很簡單了, 阿上次不是說要講 AST? 嗯……下次吧,我是個沒信用的人 XD 最近先翻 C++0x rvalue reference 的文章,我覺得這比較有趣 XD -- To iterate is human, to recurse is divine. 遞迴只應天上有, 凡人該當用迴圈.   L. Peter Deutsch --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.110.239 ※ 編輯: yoco315 來自: 118.160.110.239 (02/13 22:09)
1F:→ tsaiminghan:看起來好有趣, 要是大學修編譯器的時候有看到就好了 02/13 22:25
2F:推 legendmtg:yoco大大 <(_ _)> 02/13 22:42
3F:推 legendmtg:xyz那邊是不是把if打成return了? 02/13 22:45
4F:推 ledia:推一個~ 02/13 23:07
※ 編輯: yoco315 來自: 118.160.105.131 (02/14 00:38)
5F:→ yoco315:多謝抓錯 XD 02/14 00:38







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:e-shopping站內搜尋

TOP