左右递归解析器

时间:2018-09-11 07:01:25

标签: parsing haskell megaparsec

这是this question的演变。

我需要用megaparsec解析像这样的数据结构

OnError()

我想解析为类似的字符串

data Foo =
    Simple String
    Dotted Foo String
    Paren String Foo

例如,字符串foo ::= alphanum | foo "." alphanum | alphanum "(" foo ")" 应该解析为"a(b.c).d"

我的问题是,这同时是左递归和右递归。

对于第一种和第三种情况,编写解析器没有问题:

Dotted (Paren "a" (Dotted (Simple "b") "c")) "d"

但是我不能将第二种情况的解析器也放在一起。我尝试使用parser :: Parser Foo parser = try (do prefix <- alphanum constant "(" content <- parser constant ")" pure $ Paren prefix content ) <|> Simple alphanum sepBy1来解决这个问题,但我做对了

1 个答案:

答案 0 :(得分:3)

要在其中排除左递归:

foo ::= alphanum
    | foo "." alphanum
    | alphanum "(" foo ")"

您可以先将其重写为:

foo ::= alphanum ("(" foo ")")?
      | foo "." alphanum

然后,您可以使用替换的标准技巧排除左递归:

x ::= x y | z

使用:

x ::= z x'

x' ::= y x' | ∅

换句话说:

x ::= z y*

x = fooy = "." alphanumz = alphanum ("(" foo ")")?的情况下,变为:

foo ::= alphanum ("(" foo ")")? ("." alphanum)*

然后,我相信您的解析器可能只是这样,因为?〜零或一个〜Maybeoptional*〜零或更多〜{{ 1}}〜[]

many