我有一个编程语言语法我想在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]
这似乎有效,但我想知道是否有其他解决方案。
答案 0 :(得分:3)
目前,PetitParser并不直接支持将复合解析器拆分为多个PPCompositeParser
子类。
请记住,如果您使用PetitParser浏览器,则无需担心实例变量,它们会自动为您管理。此外,您不一定需要每个生产的实例变量。例如,终端可以是您直接调用的方法。
你的解决方案肯定也有效,但它不是那么好,因为它需要你仔细注意你想要如何连接你的语法。同样在您的实现中,您应该懒惰地缓存结果,否则您的代码将在解析时创建新的复合解析器。这非常昂贵。
除此之外,肯定有可能改进PPCompositeParser
以支持多个子类之间的依赖关系,例如通过声明构造函数将准备,初始化并最终解析的依赖性其他解析器。