С Parsec, как мне разобрать ноль или более foo1, оканчивающихся на foo2 и разделенных точкой? - PullRequest
3 голосов
/ 03 марта 2010

То, что я пытаюсь сделать, кажется довольно простым, но, поскольку я новичок в Haskell, парсек, решение ускользает от меня.

У меня есть два парсера, скажем, foo1 и foo2, где foo1 может анализировать промежуточный термин, а foo2 анализирует конечный термин. Термины разделены символом ".".

Предложения, которые мне нужно разобрать:

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

и т. Д.

Моя первоначальная мысль была сделать

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

но это не поймало бы дело foo2.

Ответы [ 4 ]

3 голосов
/ 04 марта 2010

Вы хотите 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
         ...
2 голосов
/ 04 марта 2010

Сначала вы хотите endBy вместо sepBy:

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

Во-вторых, это будет

поймать случай просто foo2

Из документации :

endBy p sep анализирует ноль или более вхождений p, разделенных sep Возвращает список значений, возвращаемых p.

0 голосов
/ 03 марта 2010

конечно, это поймает случай foo2.Использование для вашего foo1, слово Лейдена:

let a = sepBy word (char '.')
parseTest a "foo.bar.baz"
parseTest a "foo"
parseTest a ".baz"
0 голосов
/ 03 марта 2010

Попробуйте что-то вроде

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

(просто эскиз, конечно.)

В общем случае комбинатор many является эквивалентом Парсека Звезда Клини ;и если вы собираетесь добавить что-то простое, такое как конечная точка, в существующий синтаксический анализатор, использование >> / >>= может на самом деле быть чище и проще, чем использование записи do.

...