《领域特定语言》一3.2解析器的工作方式

3.2解析器的工作方式

所以,内部DSL和外部DSL的差别主要体现在解析上。虽然二者确实存在一些细节上的不同,但它们也有很多共通之处。
一个最重要的共同点就是,解析都是一个很强的层级操作。当解析文本时,把数据块组织成一个树结构。考虑一个简单结构,状态机中的事件列表。在外部DSL语法中,它看起来如下所示:

events
  doorClosed D1CL
  drawerOpened D2OP
end

这个复合结构是一个事件列表,包含一系列事件,每个事件都有名字和代码。
用Ruby编写的内部DSL与上述代码很类似:

event :doorClosed "D1CL"
event :drawerOpened "D2OP"

对于整个列表,这里没有显式的标记,但是每一个事件本身仍是一个层级:每个事件都有表示名字的符号和表示代 码的字符串。
无论何时看到这样的脚本,都可以把它想象为一个层级,这样的层级称为语法树(或者解析树)。任何脚本都可以转化为许多潜在的语法树─这取决于如何分解它。相对于单词(word),语法树是一种更有效的脚本表现形 式,因为可以遍历语法树,使用各种不同的方式来对它进行操作。
如果用到“语义模型”(第11章),可以把一个语法树翻译成语义模型(见图3-2)。如果经常读一些语言社区的资料,我们会发现,语法树得到了非常多的关注─人们通常直接执行语法树,或者基于语法树生成代码。更有效的做法是,语法树可以直接当做语义模型来使用。但大多数时候,我不会这么做,因为语法树同DSL脚本关联非常紧密,这样做只会让DSL的处理同语法产生耦合。

目前为止,我都一直都在谈论语法树,仿佛它是系统里一种有形的数据结构,就像XML DOM一样。有时候,它的确是,但更多的时候,它不是。很多时候,语法树在调用栈中形成,在遍历的过程中得到处理。所以,我们看不到整个树,而只能看到当前处理的分支(类似于XML SAX的工作方式)。尽管如此,尝试理解隐匿于调用栈中鬼魅般的语法树总是有帮助的。对一个内部DSL而言,语法树的形成有赖于方法调用(“嵌套函数”(第34章))的实参和嵌套对象(“方法级联”(第35章))。有时候,我们看不到一个很明显的层次结构,不得不进行模拟(有层次结构的“函数序列”(第33章)可以由“语境变量”(第13章)模拟)。语法树或许形似鬼魅,但它依然是一种有益的脑力工具。使用外部DSL会产生一个更加显式的语法树,事实上,有时候我们确实生成了一个完完全全的语法树数据结构(“树的构建”(第24章))。但即使是外部DSL,通常在处理过程中,也是在调用栈中不断形成和修剪着语法树。(这里引用了几个尚未描述的模式,如果是第一次读到,放心略过即可,但以后再读,这些引用会很有帮助。)

时间: 2024-07-30 02:12:50

《领域特定语言》一3.2解析器的工作方式的相关文章

《领域特定语言》一导读

前 言 在我开始编程之前,DSL(Domain–Specific Language,领域特定语言)就已经成了程序世界中的一员.随便找个UNIX或者Lisp老手问问,他一定会跟你滔滔不绝地谈起DSL是怎么成为他的镇宅之宝的,直到你被烦得痛不欲生为止.但即便这样,DSL却从未成为计算领域的一大亮点.大多数人都是从别人那里学到DSL,而且只学到了有限的几种技术. 我写这本书就是为了改变这个现状.我希望通过本书介绍的大量DSL技术,让你有足够的信息来做出决策:是否在工作中使用DSL,以及选择哪一种DSL

如何设计一门编程语言(十) 正则表达式与领域特定语言(DSL)

几个月前就一直有博友关心DSL的问题,于是我想一想,我在gac.codeplex.com里面也创建了一些DSL,于是今天就来说一说这个事情. 创建DSL恐怕是很多人第一次设计一门语言的经历,很少有人一开始上来就设计通用语言的.我自己第一次做这种事情是在高中写这个傻逼ARPG的时候了.当时做了一个超简单的脚本语言,长的就跟汇编差不多,虽然每一个指令都写成了调用函数的形态.虽然这个游戏需要脚本在剧情里面控制一些人物的走动什么的,但是所幸并不复杂,于是还是完成了任务.一眨眼10年过去了,现在在写Gac

《领域特定语言》一第2章 使用DSL 2.1定义DSL

第2章 使用DSL 看过上一章的例子后,即便尚未给出DSL的一般定义,对于何为DSL,你也应该已经有了自己的认识.(第10章中有更多例子.)现在,要开始讨论DSL的定义及其优势与问题.这样就可以为下一章讨论DSL实现提供一些上下文. 2.1定义DSL "领域特定语言"是一个很有用的术语和概念,但其边界很模糊.一些东西很明显是DSL,但另一些可能会引发争议.这一术语由来已久,不过,正如软件行业中的很多东西一样,它也从未有过一个确切的定义.然而,就本书而言,定义是非常有价值的.领域特定语言

《领域特定语言》一第1章 入 门 例 子1.1 哥特式建筑安全系统

第1章 入 门 例 子 落笔之初,我需要快速地解释一下本书的内容,就是解释什么是领域特定语言(Domain– Specific Language,DSL).为达此目的,我一般都会先展示一个具体的例子,随后再给出抽象的定义.因此,我会从一个例子开始,展示DSL可以采用的不同形式.在第2章里,我会试着把这个定义概括为一些更广泛适用的东西. 1.1 哥特式建筑安全系统 在我的童年记忆里,电视上播放的那些低劣的冒险电影是模糊却持久的.通常,这些电影的场景会安排某个古旧的城堡.密室或走廊在其中起着重要的作

《领域特定语言》一3.6 测试DSL

3.6 测试DSL 过去二十年,我变得越来越不想谈论测试.我已然成为一个忠实粉丝,迷恋着测试驱动开发 [Beck TDD]以及类似的技术:将测试置于程序设计之前.所以,我已无法脱离测试思考DSL.对DSL而言,我把其测试分为三个独立的部分:"语义模型"(第11章)的测试,解析器的测试,以及脚本的测试. 3.6.1语义模型的测试 我首先想到的部分是"语义模型"(第11章)的测试.这些测试用来保证语义模型能够如预期般工作,也就是说,当执行模型时,根据编写的代码,它能够产

实例分析浏览器中“JavaScript解析器”的工作原理_javascript技巧

浏览器在读取HTML文件的时候,只有当遇到<script>标签的时候,才会唤醒所谓的"JavaScript解析器"开始工作. JavaScript解析器工作步骤: 1."找一些东西": var. function. 参数:(也被称之为预解析) 备注:如果遇到重名分为以下两种情况: 遇到变量和函数重名了,只留下函数 遇到函数重名了,根据代码的上下文顺序,留下最后一个 2.逐行解读代码. 备注:表达式可以修改预解析的值 JS解析器在执行第一步预解析的时候,会

《领域特定语言》一3.4 解析中的数据

3.4 解析中的数据 当解析器执行时,它需要存储解析过程中的数据.这些数据可能是一个完整的语法树,但大多数情况下不是这样的.即使这种情况出现了,还是需要存储其他的一些数据,以便解析工作可以正常进行.解析本质上是一种树遍历(见图3-3),当处理某一部分DSL脚本时,对于正在处理的语法树分支,我们可以得到其上下文的一些相关信息.然而,通常我们还会用到这个分支以外的信息.我们再从状态机的例子里选取一段代码看看: commands unlockDoor D1UL end state idle actio

《领域特定语言》一1.3 为格兰特小姐的控制器编写程序

1.3 为格兰特小姐的控制器编写程序 至此,我们已经实现了状态机模型,接下来,就可以为格兰特小姐的控制器编写程序了,如下所示: Event doorClosed = new Event("doorClosed", "D1CL"); Event drawerOpened = new Event("drawerOpened", "D2OP"); Event lightOn = new Event("lightOn&quo

《领域特定语言》一2.4 广义的语言处理

2.4 广义的语言处理 本书是关于领域专用语言的,但它也涉及语言处理技术.之所以二者重合,是因为在普通的开发团队里,用到语言处理技术的情况,90%都是为了DSL.但是,这些技术也可以用于其他方面,若不讨论这些情况,将是我的失职.我曾遇到过这方面一个很好的例子,那是在一次拜访ThoughtWorks项目团队时.他们有一个任务,要与某第三方系统通信,发送的消息以COBOL copybook定义.COBOL copybook是一种用来描述记录的数据结构格式.因为系统中有很多地方要用到,所以我的同事Br