跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何在 Java 中利用 解释器模式 为特定领域语言(DSL)构建抽象语法树的对象表示

Java中用解释器模式构建DSL的AST,需将文法规则映射为类,划分终结符(如NumberExpression)与非终结符(如AddExpression),手动组合对象形成树,Context传递只读共享数据,各interpret()方法职责单一、可独立测试。 在 Java 中用解释器模式为 DSL 构建抽象语法树(AST),核心是把 DSL 的每条文法规则映射为一个 Java 类,再通过组合这些类的实例,形成一棵可递归遍历的树。关键不在于写多少代码,而在于清晰划分终结符与非终结符、统一解释入口、让树结构自然反映语义逻辑。 明确 DSL 文法并划分表达式角色 先用 BNF 或类似方式定义 DSL 的最小语法单元。例如,一个简单算术 DSL 可定义为: expression ::= term | expression "+" term | expression "-" term term ::= number | "(" expression ")" number ::= 正整数(如 123) 据此划分角色: AbstractExpression :声明
interpret(Context ctx)
方法,所有节点都实现它 TerminalExpression :如
NumberExpression
,直接返回字面值,不递归 NonterminalExpression :如
AddExpression
、
SubtractExpression
、
GroupExpression
,内部持有一个或多个子表达式引用,解释时委托子节点并组合结果 用组合方式构建 AST 对象树 AST 不是解析器自动生成的,而是由客户端(比如词法+语法分析器)手动 new 出来的对象树。例如对字符串
"3 + (4 - 1)"
: 立即学习 “ Java免费学习笔记(深入) ”; Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 先识别出数字 3 → 创建
NumberExpression(3)
识别 '+' → 创建
AddExpression(left, right)
,其中 left 是上面的 3 节点 识别 '(' → 触发进入子表达式,解析出
4 - 1
得到
SubtractExpression(NumberExpression(4), NumberExpression(1))
将该减法节点作为 right 填入 AddExpression 最终得到的对象结构就是一棵真正的 AST:根是 AddExpression,左子是 NumberExpression(3),右子是 SubtractExpression,其下再挂两个 NumberExpression。这棵树完全由 Java 对象构成,无字符串拼接、无反射、不依赖外部库。 Context 传递共享上下文信息 Context 不是必须的全局变量,而是解释过程中可能需要的只读数据容器。例如 DSL 支持变量,就可在 Context 中用
Map
存变量值;若需记录解析位置或错误信息,也可放进去。每个
interpret()
方法都接收它,但只读不修改——保证解释过程无副作用,便于测试和复用。 保持解释逻辑单一且可测 每个表达式类的
interpret()
方法只做一件事:对自身语义求值。例如:
NumberExpression.interpret()
直接返回封装的 int 值
AddExpression.interpret()
调用 left.interpret() + right.interpret()
GroupExpression.interpret()
单纯返回 inner.interpret() 这样每个类职责清晰,单元测试只需构造单个对象加 Context,断言返回值即可,无需启动整个 DSL 引擎。

相关文章