【问题标题】:Self-referencing PetitParser's PPCompositeParsers自引用 PetitParser 的 PPCompositeParsers
【发布时间】:2013-03-13 16:05:35
【问题描述】:

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

我的问题是这些子文法有循环依赖:结构文法引用了语句文法的'statement'规则,它引用了表达式文法的'expression'规则,又引用了结构语法(关闭依赖循环)。我尝试了简单的方法,例如,在表达式语法中使用 #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]

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

【问题讨论】:

    标签: smalltalk pharo petitparser


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 更新: 我发布了一个实验版本(PetitParser-lr.230),它添加了一流的依赖项:(1)添加一个方法#dependencies,它返回一个集合依赖的复合解析器,以及 (2) 通过dependencyAt: 访问这些依赖的解析器。检查方法 cmets。像这种不同类之间的循环依赖关系应该开箱即用。
    • 你的更新很棒!我的代码现在更简单更快了:-)。谢谢卢卡斯
    猜你喜欢
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2020-12-07
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多