Разобрать список, разделитель которого также может стоять в конце

Я пытаюсь разобрать какой-то текст, но не могу понять, как разобрать список символов, разделенных каким-то разделителем, который может встречаться, а может и не встречаться в конце списка.

Пример (числа, разделенные пробелами):

set A = 1 2 3 4 5;
set B =6 7 8 9;
set C = 10 11 12 ;

Если я использую sepBy, после последнего пробела я получаю сообщение об ошибке, потому что он ожидает другую цифру, даже если я пытаюсь прочитать также many whitespace после списка. Если я использую endBy, я получаю сообщение об ошибке, когда пробел отсутствует.

import Text.ParserCombinators.Parsec

main :: IO ()
main = do
  let input = "set A = 1 2 3 4 5;\n" ++
              "set B =6 7 8 9;\n" ++
              "set C = 10 11 12 ;\n"
  case parse parseInput "(unknown)" input of
    Left msg ->
      print msg
    Right rss ->
      mapM_ (\(n, vs) -> putStrLn (n ++ " = " ++ show vs)) rss

whitespace :: GenParser Char st Char
whitespace = oneOf " \t"

parseInput :: GenParser Char st [(String, [Int])]
parseInput = parseRow `endBy` newline

parseRow :: GenParser Char st (String, [Int])
parseRow = do
  string "set"
  many1 whitespace
  name <- many1 alphaNum
  many whitespace
  string "="
  many whitespace
  values <- many1 digit `sepBy` many1 whitespace
  many whitespace
  string ";"
  return (name, map read values)

person Claudio    schedule 07.06.2013    source источник
comment
Этот предыдущий вопрос может быть какой-то пользой.   -  person rickythesk8r    schedule 07.06.2013


Ответы (1)


Я думаю, вам нужен комбинатор sepEndBy. Его использование дает вам

-- I'm using the type synonym
-- type Parser = GenParser Char ()
-- from Text.ParseCombinator.Parsec.Prim
parseRow :: Parser (String, [Int])
parseRow = do
  string "set" >> many1 whitespace
  name <- many1 alphaNum
  spaces >> char '=' >> spaces
  values <- many1 digit `sepEndBy` many1 whitespace
  char ';'
  return (name, map read values)
  where spaces = many whitespace
person Daniel Gratzer    schedule 07.06.2013