OData(02) - Irony构建OData文法,悲剧的Babelua
之前提到要实现OData协议,如果你之前没了解过OData那么也想不到在URL这有限的字符串中会有如此复杂的一个协议,复杂到用一般的解析手段根本不可能完成分析工作。
OData协议简单介绍OData协议官方网址如下所示:
OData协议主要分为下面几个部分:
协议正文:主要定义了HTTP通讯中请求和响应的格式、数据模型及元数据模型。
URL约定:请求时的URL格式,主要定义了各种查询的URL格式,这个约定还有一个补充协议主要是针对数据聚合查询。
数据往返格式:主要就是XML和JSON这两种
主要就是上面这些,然而最为复杂的是第二部分,URL约定还有专门的ABNF定义,主体的定义就有1000多行了,所以想要成功的完整分析OData的URL就需要一个小型的编译过程才行,实现编译过程第一步就是进行词法分析、语法分析这些工作,包含微软官方的OData实现也是这么干的,有兴趣朋友可以去阅读官方代码,在NET中能实现这个功能的框架我选是Irony这个框架,对于我而言选它是有历史原因。
国产免费项目的悲剧【Babelua】Babelua是一个用于编辑、调试Lua脚本的Visual Stuido扩展,支持VS2013到VS2015现在还能下载到https://marketplace.visualstudio.com/items?itemName=babestudio.BabeLua,在2015年的时候也算比较出名了,这个插件一共有三名作者,开始由另一个同事写的初版,然后我接手后和另一个C++高手重写了整个项目,我主要开发语言服务编辑功能像自动补全,代码格式化等VS实现部分,而他主要是对接调试器。这里还需要提到的是这个项目的组织者也就是我们当时的上司,由于这个完全免费的原因还有在当时具有完备编辑调试Lua代码的工具本来就比较少,所以也很快在国内外出现不少用户,这算是成绩吧,不过在我接手后这个项目没有真正公开源代码,所以也不能算开源项目。
当时Python语言在VS中还是以扩展形式安装,而且Babelua也是模仿Python for Visual Studio这个插件开发,我其实是想把Babelua的功能提升到Python扩展这个水平。很可惜这个项目是一个公司行为,由于没有任何实质的产出,估计我上司也承受了很大的公司压力,不能投入资源去做这件事情,最终也随着我和那位C++大神的离开,Babelua停止了开发维护工作最终而不了了之,到现在已有3年了吧。
今天再回头看只能感慨,太可惜了本来一个很好的项目就这么结束了。
Irony实现文法Irony这个框架是我在Babelua中用于分析Lua源代码,我们也用过10W+行的项目去长期测试过这个框架的性能及稳定性都是非常好的,不过这方面资料太少了,大多数文章都是在说编译原理的一些概念,能结合实际说明的文章简直就像大熊猫难找。这里就结合Irony框架来实际说明一下文法构建。下文中提到的编译概念就不一一说明了,相信有很多文章都会有。
分析的一般过程分析源代码就是要将文本转成编译器可操作的数据其实就是对象,例如 1+1 这个字符串被分析后就是一个二元操作对象,左表达式是常量1,左表达式也是常量1。编译分析的一般过程如下所式:
词法分析 -> 语法分析 -> 语义分析 -> 生成中间代码这个过程中各个阶段的产物如下所示:
单词 -> 语法分析树 -> 抽象语法树 -> 中间代码上面说的这些还是过于理论化了,如果按Irony实现过程而言各个阶段的产物如下所示:
Token -> ParseTreeNode -> AstNode -> LINQ表达式下面我们用个简单的实例来说明
简单文法示例如果你想创建一个自己的编程语言,需要创建一个方法类,继承自Irony.Parsing.Grammar,然后在构造函数中声明文法内容即可,下面用Irony中的示例代码来说明,如果你有详细看过龙书的话会发现下面这个例子就是该书中example 4.46的例子。
public GrammarEx446() { NonTerminal S = new NonTerminal("S"); NonTerminal L = new NonTerminal("L"); NonTerminal R = new NonTerminal("R"); Terminal id = new IdentifierTerminal("id"); S.Rule = L + "=" + R | R; L.Rule = "*" + R | id; R.Rule = L; Root = S; }Irony框架还提供了一个文法浏览及验证工具如下图所示,当你加载写好的DLL会自动出现你所定义的终结符、非终结符、产生式及转换状态等,同时可以测试验证文法的正确性。
使用Irony创建文法就是在声明终结符、非终结符及非终结符的规则,按龙书中的理论来说就是构造有穷自动机,当然是指导Irony引擎工作的有穷自动机规则,每个非终结符结点都会定义一条展开子节点的规则,当我们解析任何一份正确源代码在任何一个非终结点上都可以进行无二义性的展开子节点,就算我们成功构造了该语言的文法了。
文法冲突