【问题标题】:How does an interpreter use a DSL?解释器如何使用 DSL?
【发布时间】:2011-07-05 17:02:40
【问题描述】:

我正在为我的领域特定语言使用解释器,而不是编译器(尽管性能)。不过,我很难理解一些概念:

假设我有一个用于游戏的 DSL(XML 风格),以便开发人员可以轻松地构建对象:

<building>
  <name> hotel </name>
  <capacity> 10 </capacity> 
</building>

DSL 脚本被解析,然后会发生什么?

它是否执行现有方法来创建新建筑物?据我了解,它不会简单地将 DSL 转换为较低级别的语言(因为这需要编译)。

有人可以描述解释器将如何处理生成的解析树吗?

感谢您的帮助。

【问题讨论】:

  • (+1)有时使用解释器很好,有时使用解释器是制作编译器的中间步骤
  • 解析了一些数据后怎么办?好吧,它不仅仅是一个游戏答案,而不是编译器/解释器的答案。你想如何在你的游戏中使用已经存在的数据?

标签: parsing compiler-construction programming-languages interpreter dsl


【解决方案1】:

很大程度上取决于您的具体应用细节。例如,namecapacity 是必需的吗?我将给出一个相当笼统的答案,这可能有点矫枉过正。

假设:

  1. 所有嵌套属性都是可选的
  2. 有许多嵌套属性,可能具有不同的深度

这带来了 2 个想法:将您的解释器构建为递归下降解析器,并为您的对象使用某种构建器。在您的具体示例中,您将有一个 BuildingBuilder 看起来像(在 Java 中):

public class BuildingBuilder {
  public BuildingBuilder() { ... }
  public BuildingBuilder setName(String name) { ... return this; }
  public BuildingBuilder setCapacity(int capacity) { ... return this; }
  ...
  public Building build() { ... }
}

现在,当您的解析器遇到 building 元素时,使用 BuildingBuilder 构建建筑物。然后将该对象添加到 DSL 适用的任何上下文 (city.addBuilding(building))。

请注意,如果namecapacity 是详尽无遗的并且始终是必需的,您可以通过直接传递这两个参数来创建建筑物。您还可以构建建筑物并直接设置属性,而不是使用构建器(当您有许多属性并且所述属性既不可变又可选时,构建器模式很好)。

如果这是在非面向对象的上下文中,您最终将实现某种 buildBuilding 函数,该函数采用当前上下文和构建元素的内部 xml。实际上,您正在手动构建一个递归下降解析器,其中包含一个 xml 库,提供对单个元素的实际解析。

无论您如何实现它,您都可能会喜欢在 DSL 中的 xml 元素和解释器中的方法/对象之间进行直接语义映射。

【讨论】:

  • 这就是 SO 的用途。我应该警告你:如果你允许引用以前的脚本对象(稍后可以通过名称引用建筑物“酒店”),请创建一个哈希表接口以便于查找,但请记住要小心范围(如果你有范围) .您可以通过创建一个堆栈并让每个级别的范围在堆栈上推送一个新的哈希表来做到这一点。如果查找失败,请转到下一个级别并重试。
猜你喜欢
  • 2012-09-01
  • 2017-07-25
  • 2015-03-23
  • 2011-12-03
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
相关资源
最近更新 更多