使用Parsec,我如何解析由foo2终止的零个或多个foo1并且全部用点分隔?

时间:2010-03-03 18:28:07

标签: haskell parsec

我想要做的事情看起来很简单,但由于我是一个parsec Haskell newb,解决方案就是在逃避我。

我有两个解析器,比方说foo1foo2,其中foo1可以解析一个中间词,foo2解析一个结束词。术语以符号"."分隔。

我需要解析的句子是

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

等等。

我最初的想法是

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

但这不会引起foo2 - 唯一的情况。

4 个答案:

答案 0 :(得分:3)

您需要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
         ...

答案 1 :(得分:2)

首先,您需要endBy而不是sepBy

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

其次,它会

  

抓住刚才的foo2案例

来自documentation

  

endBy p sep解析p出现的{strong>零个或多个,由sep分隔。返回p返回的值列表。

答案 2 :(得分:0)

尝试类似

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

(当然只是草图。)

一般来说,many组合子是Parsec相当于Kleene star;如果你要在现有的解析器中添加一些简单的跟踪点,使用>> / >>=实际上可能比使用do表示法更简洁,更简单。

答案 3 :(得分:0)

肯定的是,它会抓住foo2的情况。使用你的foo1,莱顿的话:

let a = sepBy word (char '.')
parseTest a "foo.bar.baz"
parseTest a "foo"
parseTest a ".baz"