数学表达式解析器的设计问题

Design Problems with Mathematical Expression Parser

我正在编写一个解析数学表达式和 returns 抽象语法树的表达式求值器。我的树由运算符节点、数字节点和变量节点组成。这些中的每一个都实现了 ASTNode 接口,该接口需要实现 getValue() 方法。


运营商节点

我的第一个设计问题来自运算符节点。我有一个抽象运算符 class,其中包含有关优先级、运算符是一元还是二元以及运算符是否是右结合的信息字段。这些字段是通过受保护的构造函数设置的。有一个抽象方法 operate() 允许客户端扩展运算符 class 并创建自己的运算符。我还有一些默认运算符,它们存储在静态 DEFAULT_OPERATORS HashMap 中。每个运算符节点存储一个运算符和操作数,它们只是其他 ASTNodes。当在运算符节点上调用 getValue() 时,它会获取其参数节点的值,然后 returns 使用其运算符定义的操作的结果。每个操作员只能存在一次,因为几个不同的操作员节点可以指向同一个操作员,但我看不出有什么办法可以强制客户端维护它。例如,树中的 ever plus 节点应该共享相同的 plus 运算符实例。


变量节点

这个问题没有那么复杂。变量节点只是 returns 由客户端设置的变量值。我打算将变量的值存储在将名称映射到值的 HashMap 中。但是这个 HashMap 存储在哪里以及它如何与树相关联。变量节点是叶子,所有变量节点都需要访问 HashMap,但必须从只能访问树根的客户端设置值。我需要某种方法使树中的每个节点都可以全局访问变量 HashMap,我宁愿避免为每个节点提供对具有设置值能力的地图的引用。

至于运算符是(或不是)单例实例,如果您的运算符实现没有状态,那应该不会真正构成问题。如果他们确实有状态,那么客户端实现者的工作就是保证他们不会被搞砸。我不确定在 "API" 端你能做些什么。

至于变量查找问题,您的 evaluate(或 getValue)方法应该采用 context 参数,这将允许查找变量值。这也允许您拥有设置变量的运算符。