4

我正在尝试做的事情似乎很简单,但由于我是一个 parsec Haskell 新手,所以解决方案让我望而却步。

我有两个解析器,假设在哪里可以解析中间词并foo1解析结尾词。术语用符号分隔,。foo2foo1foo2"."

我需要解析的句子是

  • foo2
  • foo1.foo2
  • foo1.foo1.foo2

等等。

我最初的想法是做

do k <- sepBy foo1 (char'.')
   j <- foo2

但这不会抓住foo2-only 的情况。

4

4 回答 4

4

你想要endBy,没有sepBy

foo = do k <- foo1 `endBy` char '.'
         j <- foo2
         ... 

这将强制分隔符在每次出现foo1.

当然,endBy可以简单地替换为many,这可能更清楚。

foo = do k <- many $ foo1 <* char '.' 
         j <- foo2
         ...

或者,没有Control.Applicative

foo = do k <- many $ do x <- foo1; char '.'; return x
         j <- foo2
         ...
于 2010-03-04T03:44:56.043 回答
2

首先,你想要endBy而不是sepBy

do k <- endBy foo1 (char'.')
   j <- foo2

其次,它会

抓住刚刚的 foo2 案例

文档中:

endBy p sep解析零次或多次出现的p,用 . 分隔sep。返回由 . 返回的值的列表p

于 2010-03-03T22:13:35.613 回答
0

尝试类似的东西

many (foo1 >>= (\v -> char '.' >> return v)) >>= \v1 ->
  foo2 >>= \v2 ->
  -- ...
  -- combine v1 & v2 somehow

(当然,只是一个草图。)

一般来说,many组合子相当于 Parsec 的Kleene star;如果您要向现有解析器添加一些简单的东西,例如尾随点,使用>>/>>=实际上可能比使用do符号更清洁和简单。

于 2010-03-03T19:27:15.683 回答
0

当然,它会捕获 foo2 案例。用于您的 foo1,莱顿的话:

let a = sepBy word (char '.')
parseTest a "foo.bar.baz"
parseTest a "foo"
parseTest a ".baz"
于 2010-03-03T19:42:21.293 回答