Smalltalk 自参考小手笔';PPS复合分离机
我有一个编程语言语法,我想在PPCompositeParser的几个子类中展开(例如,一个类将处理指令,另一个类将处理表达式,另一个类具有句柄程序结构)。我想这样做是为了避免得到一个包含数十个实例变量的大类 我的问题是这些子语法具有循环依赖性:结构语法引用语句语法的“statement”规则,它引用表达式语法的“expression”规则,它引用结构语法的“subroutiname”(关闭依赖项循环)。我尝试了简单的方法,例如,在表达式语法中有一个#subroutiname方法,它看起来像:Smalltalk 自参考小手笔';PPS复合分离机,smalltalk,pharo,petitparser,Smalltalk,Pharo,Petitparser,我有一个编程语言语法,我想在PPCompositeParser的几个子类中展开(例如,一个类将处理指令,另一个类将处理表达式,另一个类具有句柄程序结构)。我想这样做是为了避免得到一个包含数十个实例变量的大类 我的问题是这些子语法具有循环依赖性:结构语法引用语句语法的“statement”规则,它引用表达式语法的“expression”规则,它引用结构语法的“subroutiname”(关闭依赖项循环)。我尝试了简单的方法,例如,在表达式语法中有一个#subroutiname方法,它看起来像: M
MyExpressionGrammar>>subroutineName
^ N2TJStructureParser newStartingAt: #subroutineName
MyExpressionGrammar>>subroutineName
^ PPDederedParser creationBlock: [N2TJStructureParser newStartingAt: #subroutineName]
但这在初始化时失败,因为存在无限递归(显然)
为了解决这个问题,我创建了一个PPDeferedParser:
PPParser subclass: #PPDeferedParser
instanceVariableNames: 'creationBlock'
classVariableNames: ''
poolDictionaries: ''
category: 'PetitParser-Tools'
PPDeferedParser>>parseOn: aStream
^ creationBlock value parseOn: aStream
这使得前面的#子例程看起来像:
MyExpressionGrammar>>subroutineName
^ N2TJStructureParser newStartingAt: #subroutineName
MyExpressionGrammar>>subroutineName
^ PPDederedParser creationBlock: [N2TJStructureParser newStartingAt: #subroutineName]
这似乎可行,但我想知道是否还有其他解决方案。目前,PetitParser不直接支持将复合解析器拆分为多个子类 请记住,如果您使用PetitParser浏览器,则无需担心实例变量,它们会自动为您管理。此外,对于每一个产品,您不一定需要一个实例变量。例如,终端可以是直接调用的方法 您的解决方案当然也很有效,但它并没有那么好,因为它需要您仔细注意如何连接语法。此外,在您的实现中,您应该延迟缓存结果,否则您的代码将在解析时创建新的复合解析器。这个很贵
除此之外,当然可以改进
PPCompositeParser
以支持多个子类之间的依赖关系,例如通过声明构造函数将准备、初始化并最终解析的依赖其他解析器。更新:我发布了一个实验版本(PetitParser lr.230)这添加了一级依赖项:(1)添加一个方法#dependencies
,该方法返回依赖复合解析器的集合,(2)通过dependencyAt:
访问这些依赖解析器。检查方法注释。像这样,不同类之间的循环依赖关系应该是开箱即用的。你的更新很棒!我的代码现在更简单、更快:-)。谢谢卢卡斯