自引用PetitParser的PPCompositeParsers

时间:2013-03-13 16:05:36

标签: smalltalk pharo petitparser

我有一个编程语言语法我想在PPCompositeParser的几个子类中爆炸(例如,一个类将处理指令,另一个类将处理表达式,另一个类具有句柄程序结构)。我想这样做是为了避免得到一个包含数十个实例变量的大类。

我的问题是这些子语法具有循环依赖性:结构语法引用语句语法的“语句”规则,该规则引用表达式语法的“表达式”规则,该规则引用了“子程序名”。结构语法(关闭依赖关系)。我尝试了一种简单的方法,例如在表达式语法中使用#subroutineName方法,如下所示:

MyExpressionGrammar>>subroutineName
  ^ N2TJStructureParser newStartingAt: #subroutineName

但是由于无限递归(显然),它在初始化时失败。

为了解决这个问题,我创建了一个PPDeferedParser:

PPParser subclass: #PPDeferedParser
    instanceVariableNames: 'creationBlock'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'PetitParser-Tools'

PPDeferedParser>>parseOn: aStream
    ^ creationBlock value parseOn: aStream

使前面的#subroutineName看起来像:

MyExpressionGrammar>>subroutineName
  ^ PPDederedParser creationBlock: [N2TJStructureParser newStartingAt: #subroutineName]

这似乎有效,但我想知道是否有其他解决方案。

1 个答案:

答案 0 :(得分:3)

目前,PetitParser并不直接支持将复合解析器拆分为多个PPCompositeParser子类。

请记住,如果您使用PetitParser浏览器,则无需担心实例变量,它们会自动为您管理。此外,您不一定需要每个生产的实例变量。例如,终端可以是您直接调用的方法。

你的解决方案肯定也有效,但它不是那么好,因为它需要你仔细注意你想要如何连接你的语法。同样在您的实现中,您应该懒惰地缓存结果,否则您的代码将在解析时创建新的复合解析器。这非常昂贵。

除此之外,肯定有可能改进PPCompositeParser以支持多个子类之间的依赖关系,例如通过声明构造函数将准备,初始化并最终解析的依赖性其他解析器。