F# FParsec解析无序子句

F# FParsec解析无序子句,f#,fparsec,F#,Fparsec,我想解析一些语法,如下所示 OUTPUT data GROUPBY key TO location USING object 允许使用子句的GROUPBY顺序不同,但每个子句最多只能出现一次 在FParsec中有没有一种方便的或内置的方法来解析这个问题?我读了一些关于Haskell Parsec permute的问题和答案。在FParsec中似乎没有排列。如果是这样的话,那么在FParsec中构建一个置换会怎么样呢?我认为FParsec中没有置换解析器。我看到了一些你可以选择的方向 一般来说

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

OUTPUT data
GROUPBY key
TO location
USING object
允许使用
子句的
GROUPBY顺序不同,但每个子句最多只能出现一次


在FParsec中有没有一种方便的或内置的方法来解析这个问题?我读了一些关于Haskell Parsec permute的问题和答案。在FParsec中似乎没有排列。如果是这样的话,那么在FParsec中构建一个置换会怎么样呢?

我认为FParsec中没有置换解析器。我看到了一些你可以选择的方向

  • 一般来说,@FuleSnabel的建议非常合理,而且可能是最简单的实现。不要让解析器负责断言每个子句最多出现一次的属性。相反,应该分别分析每个子句,允许重复,然后检查生成的AST,如果属性不存在,则会出错

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

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

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


我知道FParsec中没有内置的方法,但有时这些属性作为AST上的语义检查更容易验证。谢谢,我使用用户状态制定了一个解决方案,以记住是否已看到用于解析当前输出语句的特定子句。看到评论和答案后,我开始在AST上验证这一点。我觉得在AST上“验证”这一点并不像我想象的那么容易。具体来说,现在有一个输出联合类型
typeoutputstatement=OUTPUT of到..
。解析器返回一个
输出语句列表
。我现在的工作是验证列表,看看是否有DUP。如何按照惯用的方式执行此操作?更具体地说,如何确定DU列表中重复的联合案例<代码>[到“foo”到“bar”;使用“aaa”;使用“bbb”…]
没有“一个真正的方法”,但一个简单的方法是将DU映射到标记(到->0,使用->1,等等),获取一组该列表,并检查输入列表的长度是否与输出集的计数相同。我想你对我的评论读得太多了。只需编写如下函数:
function TO->0 |使用->1 |……