前面讲述了如何验证语句,这章讲述如何构建一个解释器来执行语句,解释器有两种,高级解释器直接执行语句源码或AST这样的中间结构,低级解释器执行执行字节码(更接近机器指令的形式). 高级解释器比较适合DSL,而不适合通用编程语言:一般来说,DSL更需要简单.廉价的实现,不是很在乎执行效率:这个笔记只学习高级解释器,下面的文字如果提到解释器就是指"高级"解释器.为了简单起见,下面的讨论假定目标DSL是动态类型的. 解释器有两种模式: Pattern 24,Syntax-Directed In…
语句的语义取决于其语法结构和相关符号:前者说明了了要"做什么",后者说明了操作"什么对象".所以即使语法结构正确的,如果被操作的对象不合法,语句也是不合法的.语言一般有很多语义规则,有些是运行时的(dynamic semantics),比如"不能除以零"."不能越界访问数组":有些是编译时的(static semantics).运行时&编译时的界限取决于具体的语言,python是动态类型的语言,所有的值编译时都不会指定…
如果要解释执行或转换一段语言,那么就无法在识别语法规则的同时达到目标,只有那些简单的,比如将wiki markup转换成html的功能,可以通过一遍解析来完成,这种应用叫做 syntax-directed应用. 更负载的功能,需要我们在完成parse的同时构建某种中间表示形式(Intermediate representation),简称为IR.实际上,我们一般构建一种叫做AST(abstract syntax tree)的结构,它保存了所有的token以及token之间的语法关系.在一个语言应…
本章学习一种新的作用域,叫做数据聚合作用域(data aggregate scope),和其他作用域一样包含符号,并在scope tree里面占据一个位置. 区别在于:作用域之外的代码能够通过一种特殊的表达式user.name来访问数据成员:以下两个模式分别描述非面向对象语言和面向对象语言的数据聚合作用域. Pattern 18, Symbol Table for Data Aggregates,描述了如何定义和访问简单的数据聚合,比如C struct; Pattern 19, Symbol T…
前面的章节我们学会了如何解析语言.构建AST,如何访问重写AST,有了这些基础,我们可以开始进行"语义分析"了. 在分析语义的一个基本方面是要追踪"符号",符号是语句定义的变量.函数,我们通过建立一种叫做"符号表"的基础结构来完成此项工作. 有两种模式的符号表: Pattern 16, Symbol Table for Monolithic Scope,所有的符号存在于单一的作用域内,早期的BASIC使用这种模式: Pattern 17, Sym…
每个编程的人都学习过树遍历算法,但是AST的遍历并不是开始想象的那么简单.有几个因素会影响遍历算法:1)是否拥有节点的源码:2)是否子节点的访问方式是统一的:3)ast是homogeneous或heterogeneous:4)遍历的过程中是否需要修改ast:5)以何种顺序呢遍历.这一章会讨论常用的四个ast遍历模式. Pattern 12, Embedded Heterogeneous Tree Walker, AST的node类包含了对应的访问方法,后者执行嵌入的操作,并访问所有的子节点.这种…
上一章节讲述了基本的语言解析模式,LL(k)足以应付大多数的任务,但是对一些复杂的语言仍然显得不足,已付出更多的复杂度.和运行时效率为代价,我们可以得到能力更强的Parser. Pattern 5 :回朔解析器(Backtracking Parser),这种解析器晖尝试规则的每个分支来进行匹配,与LL(k)比较的话,Backtracking Parser支持任意长度的预读token,这种Parser的能力极强,运行时的代价可能会很大. Pattern 6 :Memoizing Parser, 这…
语言翻译器可以从一种计算机语言翻译成另外一种语言,比如一种DSL的标量乘法axb翻译成java就变成a*b:如果DSL里面有矩阵运算,就需要翻译成for循环.翻译器需要完全理解输入语言的所有结构,并选择输出结构:简单的关键字或模式替换几乎肯定不会奏效."语言翻译"是一个庞大的主题,这一章只关注大体的策略和几个基本模式. Pattern 29, Syntax-Directed Translator,在parser里面嵌入操作,直接产生输出: Pattern 30, Rule-Based…
在之前的几个博客中,我主要讲了两个saga的实现模式: 基于command的控制者模式 基于事件的观察者模式 当然,这些都不是实现saga的唯一方式.我们甚至可以将这些结合起来. 发布者——收集者 回顾我们的麦当劳的例子,我们可以稍稍改进一下我们的方案.我们可以通过一个command去启动一个saga,然后这个saga就会发布消息.然后saga就等待回复事件(忽略顺序): 这里有一个优点,那就是我们的saga只有一个入口.因此我们不必担心我们的saga被其他消息触发. 当你在麦当劳下一个订单的时…
https://lostechies.com/jimmybogard/2013/03/11/saga-implementation-patterns-observer/ 侵删. NServiceBus sagas 是一个Process Manager pattern的实现,在实现的时候经常使用它的一两种主要形式.虽然各有差别,但总的来说saga的实现也就总是那几种. 第一种是观察者模式.作为一个观察者,saga通过响应事件来协调业务: 观察者有一些特性: 消息以事件的形式接收 saga并不控制消…