Parsing 使ATOPASSERC解析器递归

Parsing 使ATOPASSERC解析器递归,parsing,haskell,attoparsec,Parsing,Haskell,Attoparsec,我一直在编写一个attoparsec解析器,并尝试将解析器转换为递归解析器(将它们与monad bind>>=操作符递归组合) 因此,我创建了一个函数,将解析器转换为递归解析器,如下所示: recursiveParser :: (a -> A.Parser a) -> a -> A.Parser a recursiveParser parser a = (parser a >>= recursiveParser parser) <|> return a

我一直在编写一个attoparsec解析器,并尝试将解析器转换为递归解析器(将它们与monad bind>>=操作符递归组合)

因此,我创建了一个函数,将解析器转换为递归解析器,如下所示:

recursiveParser :: (a -> A.Parser a) -> a -> A.Parser a
recursiveParser parser a = (parser a >>= recursiveParser parser) <|> return a
其中字符串
a->b
右括号和
c:d
左括号,与
绑定比
->
更紧密

a->b
的计算结果为

(ConsExpr (Choice1 (Token "a")) (Token "b"))
c:d
的计算结果为

(ConsExpr (Choice2 (Token "d")) (Token "c"))
我想我可以用
foldl
来表示一个,用
foldr
来表示另一个,但其中还有更复杂的地方。注意,它是以一种稍微奇怪的方式递归的,因此
“a:b:c->e:f->:g:h->”
实际上是一个有效的字符串,但是
“->a”
“b:
不是。最后,
fix
对我来说似乎更简单。我重命名了递归方法,如下所示:

fixParser :: (a -> A.Parser a) -> a -> A.Parser a
fixParser parser a = (parser a >>= fixParser parser) <|> pure a
fixParser::(a->a.Parser a)->a->a.Parser a
固定语法分析器a=(语法分析器a>>=固定语法分析器)纯a

谢谢。

为什么不解析一个列表,然后把它折叠成你以后想要的东西呢? 也许我错过了什么,但这对我来说更自然:

consChain :: [Expression] -> Expression
consChain = foldl ConsExpr EmptyExpr

parseExpression :: Parser Expression
parseExpression = consChain <$> many1 parseFoo
它与您的
递归解析器有很多共同之处:

  • some_v
    类似于
    parser a>>=recursiveParser-parser
  • many_v
    类似于
    recursiveParser

您可能会问,为什么我称您的递归解析器函数为非直观的。这是因为该模式允许解析器参数影响解析行为(
a->a.parser a
,记住?),这可能有用,但不明显(我还没有看到这种情况的用例)。事实上,您的示例没有使用此功能,这使它看起来多余。

附议此答案-解析列表,然后使用智能构造函数将其折叠为摘要值是惯用的解决方案。谢谢,这是我问题的一个好答案。我想很多对我不起作用的原因是我的AST实际上包含了一个选择,它不像我在问题中给出的那样简单。这是个好答案though@Rehno,您能否用一个额外的用例来扩展您的问题,在这个用例中,
recursiveParser
的功能得到了充分的利用?我很好奇。另外,我很乐意尝试改进我的答案!只是好奇-使用AttorParsec而不是使用来自Parsec 3的Stream by testring m Char有好处吗?老实说,我对haskell解析库不是很熟悉,但是AttorParsec看起来非常轻量级并且性能非常好(),这正是我在这个应用程序中想要的。另外,我也不太关心我认为Parsec的主要优点是什么样的错误消息。然而,如果我必须解析像C这样具有挑战性的东西,我肯定会选择Parsec。有趣的基准测试。我没有意识到attoparsec的性能提升不仅仅来自于ByteString的使用——这是我的假设,因为我认为它是在Parsec 2时代创建的。@monadic是的,看起来Bryan O'Sullivan真的做了一项难以置信的工作来微调它
fixParser :: (a -> A.Parser a) -> a -> A.Parser a
fixParser parser a = (parser a >>= fixParser parser) <|> pure a
consChain :: [Expression] -> Expression
consChain = foldl ConsExpr EmptyExpr

parseExpression :: Parser Expression
parseExpression = consChain <$> many1 parseFoo
many :: (Alternative f) => f a -> f [a]
many v = many_v
    where many_v = some_v <|> pure []
          some_v = (:) <$> v <*> many_v