【发布时间】:2016-05-22 12:23:27
【问题描述】:
我之前用 Marpa 成功地解析了复杂而愚蠢的旧文本格式,现在我正在尝试再做一次。
这种特殊格式有成百上千种不同的“开始”和“结束”块,如下所示:
Begin BlahBlah
asdf qwer 123
987 xxxx
End BlahBlah
Begin FooFoo
Begin BarBar
some stuff (1,2,3)
End BarBar
whatever x
End FooFoo
如何制定一条规则来匹配上述内容中的所有 BlahBlah、BarBar 和 FooFoo?我在任何示例中都看不到如何动态捕获令牌并重新使用它来终止规则,至少在标准无扫描语法示例中没有。我不想列举所有不同种类的积木,因为新种类会破坏事物,我认为没有必要。
开始/结束块的内容对问题无关紧要。实际上,这些东西是一个复杂的混乱,但没有什么我不知道如何度过难关。我对其他使 Marpa 成为一个很好的工具的复杂细节挥手致意,因此我不想求助于正则表达式。
至少我想要实现的是块类型(即“BlahBlah”)到其内容的键值映射作为字符串。
【问题讨论】:
-
我猜这以某种方式证明了我需要做的事情,但老实说它在我的脑海中航行:github.com/jddurand/MarpaX-Languages-XML-AST/blob/master/lib/…
-
首先,您需要一个用于嵌套的“堆栈”——参见 perl 的
push和pop。您需要在任何给定时间查找的唯一有效End xxx是堆栈顶部的xxx。至于“内容”,例如some stuff成为 FooFoo 内容的一部分(以及 以及 和 BarBar)? -
在我脑海中,玛尔巴有两种方法。一种是对“结束”分隔符的标记使用事件,并手动确保分隔符在解析时匹配。这具有允许“快速失败”的优点。但是,如果分隔符是真正嵌套的(也就是说,它们相互跨越是无效的),您可以在解析时不匹配它们,然后检查它们是否匹配评估。这可能会更好,因为它允许更好的错误消息和更多的评估。
-
我有理由确定所有的嵌套都是“真”的,我可以在“结束”字符串之后抛出重复的标记。所有块可能都由字符串“Begin”和“End”充分分隔。我只是希望有一个可爱的句法技巧来重复标记。我想我会扔掉/忽略重复标记并希望最好,而不是诉诸词位暂停事件。
-
我玩弄了各种关于此类技巧的想法,但从未实施过。请注意,您可以做一个混合解决方案——忽略重复标记,但保存它并在评估期间检查它是否正确——在评估该规则时,您将同时拥有两者,并且您可以发出一个非常酷的错误消息来描述不匹配完全正确。