C_and_CPP 板


LINE

Yet Another Recursive Descent (YARD) parsing framework for C++ 网站 http://code.google.com/p/yardparser/ 网站上面没有什麽教学,只有下载,然後抓下来的东西里面有 demo 程式, 因为本身非常简单,所以大致上是看了就懂,但是我还是想写一篇教学, 这样大家可以减少一点摸索的时间。 这篇文章会先介绍 yard 跟其他 parsing gramework 的比较, 然後我会从非常简单的范例开始出发,一直到最後给一个很难的范例, 让你们熟悉如何使用 yard 建立自己的 grammar。 在学会了如何使用 yard 建立自己的 grammar 之後, 我会示范如何使用 yard 来自动建立 abstract syntax tree (AST), 并且把 yard 使用在自己的程式里面。 优缺点分析: 跟 boost::spirit 的比较 yard 跟 boost::spirit 一样的地方是他们的 grammar 都不限於 LR(1), 可以写 EBNF 的 parsing rule,语法好写好读。 boost::spirit 强势的地方在於支援 dynamic parsing, 也就是 parsing rule 可以在 runtime 动态改变。 boost::spirit 最大的弱点在於编译效能, boost::spirit 很难用来开发大型的 parser, 当你的 parsing rule 到了 30~40 以後,编译时间就快要一个小时, 一个 78 parsing rule 的 grammar,编译要两个小时[1]。 执行效能也是 boost::spirit 的一个问题, 每个 parsing rule 被引用的时候,都涉及一次 virtual function 的呼叫。 相较於此,yard 的编译速度非常快速! 编译完整的 c 语言语法 + XML 语法 + scheme 语法,全部加起来不用一秒。 跟 yacc 的比较 没什麽好比的 -________-|| yacc 再见再见 简单教学范例 好,在使用 yard 的时候,我们都要 include <yard.hpp>, 如果你要 parse 一般简单的文字的话,顺便 include <yard_text_grammar.hpp>, 然後为了方便,就 using namespace 吧! 所以你开发的每个 grammar 原始码架构大概是这样的。 == my_grammar.hpp == #include <yard.hpp> #include <yard_text_grammar.hpp> namespace my_grammar { using namespace yard ; using namespace yard::text_grammar ; /*...[[[ 这边就是我们要写自己的 grammar 的地方 ]]]... } 那这篇文章之後的范例就不写这部份了,只着重在 grammar 的地方。 yard 的设计是建立在 C++ 强大的 template 机制上面, 每一个 parsing rule 就是一个 struct, 藉由组合不同的 struct 来完成复杂的 grammar。 先来一个最简单的例子 // AB struct AB : CharSeq < 'A', 'B' > {} ; 这样就完成一个可以用来 parse "AB" 这个字串的 rule 了, CharSeq 是 yard 里面已经定义好的 struct, 会从来源读入一个一个字元来进行 match 的动作。 实做细节其实很不难,但是很有创意!有兴趣的去看翻一下原始码就知道。 再来一个稍微难一点的 // (AB)* struct ABAB : Star < AB > // 这边 AB 当然是接续前面的范例 {} 不用说,Star 也是 yard 里面已经定义好的一个 struct, 可以 match 零到无限多个你放在 < > 里面当作 template 参数的规则。 接下来是… // ABC(AB)* struct ABC_ABAB : Seq < CharSeq < 'A', 'B', 'C' >, ABAB > {} ; Seq 也是 yard 已经有的 struct,可以用来 match 一串序列的 rule, 他跟 CharSeq 一样都可以接不同数量的 template 参数, 但是也不是没有上限,他内部设计是 10 还是 16 我忘记了, 你可以自己改,但是最後的限制会取决於你的编译器所支援的上限。 有的时候你会想 match 多种可能的其中一种 // (AB|XYZ) struct AB_or_XYZ : Or < AB, CharSeq < 'X', 'Y', 'Z' >, > {} ; 当你用 Or 的时候,你就可以只 match 其中一种 rule, 注意一下,当某个顺序在前面的 rule match 成功的时候,match 就结束, 这跟一般我们 C/C++ 预设的 operator || 行为一样,因为 Or 底层就是这样实做的。 所以注意下面这个例子 Or < CharSeq<'A','B'>, CharSeq<'A'> > match "A" Or < CharSeq<'A','B'>, CharSeq<'A'> > match "AB" Or < CharSeq<'A'>, CharSeq<'A','B'> > match "A" Or < CharSeq<'A'>, CharSeq<'A','B'> > not match "AB" 因为当 rule 看到第一个 'A' 的时候,rule 会把这个 'A' 消耗掉, 剩下一个 'B',但是你的 grammar 已经结束了,所以 parsing 失败。 上面的例子为了示范,都非常简单, 但是你其实可以用 yard 直接建立非常复杂的 rule, 例如: // (+|-)?[0-9]\+(\.[0-9]\*)? 就是一般的浮点数啦 struct number : Seq < Opt < Or < Char<'+'>, Char<'-'> > >, // (+\-)? Plus < Digit >, // [0-9]+ Opt < Seq < Char<'.'>, Star < Digit > > // (.[0-9]*)? > {} ; 最後总结一下: yard 让你可以用高阶的语法写成 parsing rule,这点跟 boost::spirit 一样, 平心而论,template 写起来比起 boost::spirit 的 operator overloading 是稍微麻烦了一点,但是 boost::spirit 的编译时间实在让人不敢恭维。 yard 本质上是一个 recursive descent parser generator, 执行速度非常快,他跟你用手写出来的 recursive descent parser 一样好, 如果你要处理的东西不需要 dynamic parsing,那 yard 会是你的第一选择。 yard 跟 boost::spirit 一样,支援自动的 abstract syntax tree (AST) 生成, 我很想继续写下去,但是刚刚右下角跟我说活屍日记完档了, 所以 AST 跟怎麽在自己的程式当中使用 yard 就下次再说,先这样罗掰。 [1] http://nedbatchelder.com/blog/200409/spirit_parser_framework.html 记错了,是两个小时,本文更正,文章没有讲他用的是什麽机器。 -- To iterate is human, to recurse is divine. 递回只应天上有, 凡人该当用回圈.   L. Peter Deutsch --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.160.120.198
1F:推 revivalworld:推~ 01/22 23:09
2F:推 StubbornLin:好像蛮少机会自己写parser的 XD 除了修compiler 01/22 23:30
3F:→ StubbornLin:不过还是推 01/22 23:30
4F:推 tinlans:请问计算编译时间用的机器是什麽呢? 01/22 23:35
5F:推 softwind:推~ 有教学就推啦 01/22 23:42
6F:推 legendmtg:感谢yoco大大 <(_ _)> 01/22 23:46
7F:推 UNARYvvv:推啊~期待续作 01/23 05:01
8F:推 bugmens:想当初修系统程式时,老师要我们找资料去写yacc lex的范例 01/23 07:51
9F:→ bugmens:搞了老半天都最简单的四则运算都试不出来,期待大大下次的 01/23 07:53
10F:→ bugmens:范例 01/23 07:53
11F:→ MOONRAKER:噗,lex/yacc其中一个manpage就有四则运算 01/23 10:17
12F:→ MOONRAKER:lex/yacc学校上课可能教得鸦鸦乌,可是试不出来…哈。 01/23 10:18
13F:推 mizuki2005:只能给推了... 01/23 13:32
14F:推 mantour:不推不行… 01/23 14:23
15F:推 aecho:不推对不起自己阿~~ 01/23 22:21
※ 编辑: yoco315 来自: 118.160.120.163 (01/24 00:44)
16F:推 icespeech:推...早点看到这个多好 XD 01/24 02:39
17F:推 robinhood:第一页第二段的 framework 误植为 gramework 了? 01/24 17:43
18F:推 kkc:好文推~ 02/13 22:26
19F:→ yoco315:我的妈阿... yard 写起来怎麽这麽麻烦..........好烂... 01/03 23:08







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灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP