这是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
来解决这个问题,但我做对了
答案 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
= foo
,y
= "." alphanum
和z
= alphanum ("(" foo ")")?
的情况下,变为:
foo ::= alphanum ("(" foo ")")? ("." alphanum)*
然后,我相信您的解析器可能只是这样,因为?
〜零或一个〜Maybe
〜optional
和*
〜零或更多〜{{ 1}}〜[]
:
many