上周的工作任务中,有与引擎通过json数据交互的过程。我的工作是给motion builder开发插件,插件与unreal间的沟通通过json数据包。我也是闲的蛋疼,懒得去网上搜索下载json解析库,主要是懒得去学习那些库的使用接口,就自己花一点时间弄了一个.h和.cpp文件来干这事,编译到插件里,简单直接,没那么多废话。
由于有之前解析xml的经验,这次几乎就直接很顺利的写好了。json格式参考www.json.org
上次解析xml的经验看这里:http://my.oschina.net/zhoubaojing/blog/181256
这次json解析的代码在这里:http://git.oschina.net/zbjxb/jsonParser
两个解析的方法一模一样,没有任何创新,这个模式与一般的编译理论前端的写法有点差异,主要的就是书本理论里的前端都会搞出两个部分:词法分析器+语法解析器。而我这两个解析的东西似乎和那个对不上号。不过这其实只是表象啦,本质没有任何区别,又阅读了http://www.compilers.iecc.com/crenshaw/tutor7.txt 这篇文章一遍,理解得就更清楚了。
总结一下就是:
一门type2(context-free)或type3(regular)型语言,可以用一堆BNF来表示。这些BNF都是用来描述语法的,也就是描述什么样的字符串是合法的,但是它表达不了语义,即无法表达一串字符代表什么含义。
BNF里描述的概念其实就是一个个有穷自动机。比如Number的构成就是一个自动机,String的构成的就是一个自动机,操作符的构成是一个自动机,表达式是一个由这些小的自动机组成的更大的自动机,也就是书里说的Little machines make big machines。这一点,大家都是一致的,没有区别。
有区别的是在我的实现里,我先写了总的自动机,在总的自动机里调用了各种不同的小自动机,而且最最重要的是,在每个自动机结束的地方,直接实现了自动机代表的概念的语义。这个过程十分直接,没有弯弯绕绕。语法解析完,语义也解析完了。简单直接就是它的优点。缺点也很明显了,如果有新的语法元素增加或改变,语义改变等等,整个解析过程的修改量可能会比较大,或者容易出错,其实就是随着自动机的增多这个量变,引起代码编写和维护难度增大这个质变。而lexical scanner的出现,就将语法部分的解析与语义部分的解析给拆开了,一个部分只关心一个problem的解决,这样就降低了思维负担。这个是独立的lexical scanner出现的唯一实践原因。
而所谓的独立lexical scanner其实非常简单。在我的代码中,parseNumber函数通过Number自动机拿到组成Number的合法完整字符串后,直接返回了这个字符串的语义值,一个double值。parseArray函数通过Array自动机拿到组成Array的合法完整字符串后,直接返回了一个数组对象。等等。这就是我所说的语法解析和语义解析混合在了一起的意思。而独立的lexical scanner其实就是一个switch-case语句,每一个case都是前面使用的一个语法概念的自动机,即每一个case都能拿到一个概念的完整合法字符串,但是不解析它的语义,lexical scanner直接返回这个完整字符串,而且还额外返回一个标识这个字符串是代表什么概念的枚举值。比如,我这个json解析里就定义了(null,bool,string,number,array,object)这五个概念枚举值,当解析到了一个“true”值时,lexical scanner就应该返回字符串“true”,以及枚举值(bool),用来标识返回的字符串值是代表一个布尔值。这里,lexical scanner返回的字符串就是所谓的Token。
语法解析之后,接着就是所谓的语义解析。也就是根据返回的枚举值,来将Token解码,比如,返回的枚举值是number的话,就将Token字符串转换成double。返回的是+-*/等等运算符的话,就将运算符两边解出来的number进行四则运算得出结果,等等。这就是所谓的语义解析。
总体来说,就是所谓的Distributed和Centralized型的scanner。我用的就是分布式scanner,一般书中和实践中采用的是中央集中式的scanner。再强调一下,分布式比集中式scanner最大的优点是分布式scanner知道每次scan时的准确Token类型,直接用对应的自动机去解析语法拿到Token,而不是像集中式scanner只知道是scan一个Token,完全不考虑当前这个Token在整个语法结构中根本不可能是某些类型,造成不必要的判断。
道理就是这么个道理,因为这只是前端。麻雀虽小,五脏俱全。努力掌握小规模但结构完整的东西,是最重要的。当然,由量变引发的新问题乃至质变,也不是次要的。