【问题标题】:FParsec parse unordered clausesFParsec 解析无序子句
【发布时间】:2016-08-28 10:25:04
【问题描述】:

我想解析一些语法,如下所示

OUTPUT data
GROUPBY key
TO location
USING object

GROUPBY TO USING 子句的顺序允许变化,但每个子句最多出现一次。

在 FParsec 中是否有一种方便的或内置的方法来解析它?我阅读了一些提到 Haskell Parsec permute 的问题和答案。 FParsec 中似乎没有置换。如果这是要走的路,我将如何在 FParsec 中构建置换?

【问题讨论】:

  • 我知道 FParsec 中没有内置方法,但有时这些属性可以更容易地验证为对 AST 的语义检查。

标签: f# fparsec


【解决方案1】:

我认为 FParsec 中没有置换解析器。不过,我看到了一些你可以采取的方向。

  • 总的来说,@FuleSnabel 的建议非常合理,并且可能最容易实现。不要让解析器负责断言每个子句最多出现一次的属性。而是分别解析每个子句,允许重复,然后检查生成的 AST 并在您的属性不成立时出错。

  • 您可以生成解析器的所有排列并将它们与choice 结合起来。显然,这种方法无法扩展,但对于三个解析器,我会说这是公平的游戏。

  • 您可以编写自己的原语,以使用以任意顺序应用的解析器集合进行解析。这将是many 的变体,在每个步骤中,您创建一个解析器的choice,然后丢弃该解析器。因此,在每一步中,您都从一个不断缩小的解析器列表中进行选择,直到您无法再解析,最终返回沿途收集的结果。

  • 您可以使用user state 来跟踪已使用的解析器,如果在同一上下文中使用了两次解析器,则会失败。不确定这是否会产生一个特别好的解决方案 - 以前没有真正尝试过。

【讨论】:

  • 感谢我制定了一个解决方案,使用用户状态来记住是否已看到用于解析当前 OUTPUT 语句的特定子句。在看到评论和答案后,我开始在 AST 上进行验证。我觉得在 AST 上“验证”这一点并不像我想象的那么容易。具体来说,现在有一个 OUTPUT 联合类型 type OutputStatement = OUTPUT of .. | TO of ..。解析器返回一个OutputStatement list。我现在的工作是验证列表以查看是否有重复。如何以惯用的方式做到这一点?
  • 更具体地说,如何确定 DU 列表中的重复联合案例? [TO "foo"; TO "bar"; USING "aaa"; USING "bbb"; ...]
  • 没有“一个真正的方法”,但一个简单的方法是将 DU 映射到标签(TO -> 0,USING -> 1 等),获取一组该列表,并检查输入列表的长度是否与输出集的计数相同。
  • 我认为你对我的评论读得太多了。写一个这样的函数:function TO _ -> 0 | USING _ -> 1 | ...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多