领域专用语言实战
Debasish Ghosh[美]
2013.11出版
元编程:编写“编写代码”的代码。元编程可以通过编写程序来产生新的程序,也能改变已有程序的行为。
常用的DSL
DSL | 用途 |
---|---|
SQL | 关系型数据库 |
Ant, Rake, Make | 几种用于软件系统构建的语言 |
CSS, HTML | web开发预言 |
YACC, Bison, ANTLR | 几种用例生产语法分析器的语言 |
RSpec、Cucumber | Ruby环境下的行为驱动测试语言 |
lombok | Java-JSR-269-插入式注解处理器,编译器修改源代码 |
AspectJ | 面向切面编程aspect-oriented programming |
java字节码技术
- 动态代理 java自身使用的动态代理
- CGLIB
- javassist
- asm
java元编程能力
- jdk里的javap,用来反汇编class文件查看生成的字节码
- org.objectweb.asm 用来解析、修改、保存字节码的代码库
- fernflower.jar 用来批量将class文件反编译成java代码(当然idea也可以手动单个反编译)
- java的Instrumentation,可以编写代码使用javaagent代理执行其它java文件,在代码里使用上面的asm库动态修改代码。也可以直接将所有字节保存,并加载其它class文件。
设计DSL结构的原则
- DSL要为问题域制品提供直接的映射
- DSL脚本必须使用问题域的共通语汇
- DSL脚本必须对底层实现进行抽象
DSL的分类
内部DSL
-
内嵌式
实现模式 工具箱 灵巧API 连贯接口、java语言、Ruby语言 反射式元编程 Ruby\Groovy隐式上下文、Ruby语言动态装饰器 类型化内嵌 Scala语言类型化的抽象 语法树操作 - 元编程模式:
- 隐式上下文和灵巧API
- 利用动态装饰器的反射式元编程
- 利用builder的反射式元编程
- 类型化抽象模式
- 运用高阶函数使抽象泛化
- 运用显式类型约束建模领域逻辑
- 元编程模式:
-
生成式
实现模式 工具箱 编译时元编程 通过宏来进行代码生成,Clojure语言 运行时元编程 运行时代码生成、Ruby语言
外部DSL
- 上下文驱动的字符串
- XML转换成可使用的资源
- DSL工作台
- DSL中内嵌异质代码
- 基于解析器组合子的DSL设计
内部DSL的集成入口
内部DSL的集成模式 | 集成入口 |
---|---|
JAVA脚本引擎 | 用Groovy等脚本语言编写的DSL可以通过java脚本引擎来集成 |
DSL包装器 | 利用JRuby, Scala,Groovy等语言吧java对象包装成更灵巧的API |
语言特有的包装功能 | 通过实现一种直接加载并解析DSL脚本的程序抽象直接与java集成 |
外部DSL的集成入口
外部DSL的集成模式 | 集成入口 |
---|---|
上下文渠道的字符串操作 | 字符串经过分词处理被转化为宿主语言代码,如果正则匹配和动态代码解析 |
XML转换成可使用的资源 | XML解析器 |
非文本表述 | 非文本表示被转化成AST,根据应用本身使用的宿主语言生成一颗该语言的具体语法树 |
DSL中内嵌异质代码 | 将内嵌代码作为回调函数插入其中 |
基于解析器组合子的DSL设计 | 以宿主语言写成的组合子就是解析外部DSL的规则 |
处理错误和异常
待解问题 | DSL设计者的解决之道 |
---|---|
给异常命名 | 异常状态也是领域抽象。应当一致使用领域语言来表述过程中可能发生的任何异常 |
处理输入错误 | 1. 方法名、对象名或者其他语言主体不存在时给出提示 2. 语法解析器的功用 |
处理异常的业务状态 | 向用户提供充分的上下文信息 |
最佳实践
- 设计内部DSL的时候,应该遵循实现语言的最佳实践
- Ruby,Groovy等动态语言给与使用者非常大的元编程能力
- 对于像scala这样的实现语言,静态类型是良好的帮手
- 对应clojure这类具有编译时元编程能力的语言,请用宏来自定义语法结构
语法分析基础设施
- 词法分析
- 语法分析
- 抽象语法树
- 代码生成
语法制导翻译
- 一套上下文无关语法。它的意义是决定哪些产生式是有效的
- 一套语义规则,作用对象是语法识别的符号的属性。这些规则在生产语义模型时发挥作用
语法分析器的分类
- 简单的自顶向下语法分析器
- LL(1)递归下降分析器
- LL(k)递归下降分析器
- 高级的自顶向下语法分析器
- 递归下降回溯分析器: PEG(parsing expression grammar, 解析表达语法)
- 带中间结果记忆的分析器: Packrat分析器
- 语义谓词分析器:
- 自底向上语法分析器
- 算符优先分析器
- LR(k)分析器:移进-归约分析(shift-reduce)
- LR分析器的变体:简单LR(SLR)、前瞻LR(LALR)、规范LR(canonical LR)