
hello, i am trying to write a parser in haskell, using parsec. the task is as follows: a string shall go into a data type (String, [(String, [Integer])]). as an example: "LC.app : 0 , 2 22. abs : 1 ." shall give ("LC", [("app", [0, 2, 22]), ("abs", [1])]) the string is separated by dots, and the integers are separated by either commas or spaces (this is why i cannot use lexer). i have written the following parser, which is not elegant at all, and has the flaw that it does not accept the example because of the space between the 1 and the last dot. furthermore it won't accept newline as a separator for SepBy. -------- the types type Constructor = (String, [Integer]) type Sig = (String, [Constructor]) -- ("LC", [("app", [0, 0]), ("abs", [1])]) -------- the main parser parseString2 :: Parser Sig parseString2 = do spaces name <- word spaces eol sig <- endBy line eol return (name, sig) --------- the parser for one symbol line :: Parser Constructor line = do spaces constru <- word spaces (char ':') spaces ar <- sepBy number separator return (constru, ar) -------- the parser for the integer values number :: Parser Integer number = do ds <- many1 digit; return (read ds) -------- the end of line parser -------- two symbols are separated by at least one point or newline eol :: Parser () eol = do skipMany1 (char '.' <|> char '\n') -------- a separator between two integers is a space or a comma separator :: Parser () separator = skipMany1 (space <|> char ',') i would appreciate if somebody could help me. i tried to exploit all the manuals i found for haskell, but was not successful. greetings ben -- View this message in context: http://www.nabble.com/treating-spaces-with-Parsec-tp20857293p20857293.html Sent from the Haskell - Libraries mailing list archive at Nabble.com.

"ben.a"
"LC.app : 0 , 2 22. abs : 1 ."
[...]
line = do spaces constru <- word spaces (char ':') spaces ar <- sepBy number separator return (constru, ar)
[...]
-------- a separator between two integers is a space or a comma separator :: Parser () separator = skipMany1 (space <|> char ',')
the culprit is "sepBy number separator": for things like "1 2 " it will read a separator, and so will wait for the next number, and won't expect eol. replace "sepBy number separator" with "endBy number separator" and see it will work. this is quite ugly though since it allows "xxx : 1, ." a better solution could be to use: separated_numbers1 :: Parser [Integer] separated_numbers1 = do x <- number spaces xs <- (char ',' >> spaces >> separated_numbers1) <|> option [] separated_numbers1 return (x : xs)

The solution you suggested works really fine. Thanks a lot for your effort. ben Pixel-2 wrote:
"ben.a"
writes: [...]
"LC.app : 0 , 2 22. abs : 1 ."
[...]
line = do spaces constru <- word spaces (char ':') spaces ar <- sepBy number separator return (constru, ar)
[...]
-------- a separator between two integers is a space or a comma separator :: Parser () separator = skipMany1 (space <|> char ',')
the culprit is "sepBy number separator": for things like "1 2 " it will read a separator, and so will wait for the next number, and won't expect eol.
replace "sepBy number separator" with "endBy number separator" and see it will work.
this is quite ugly though since it allows "xxx : 1, ."
a better solution could be to use:
separated_numbers1 :: Parser [Integer] separated_numbers1 = do x <- number spaces xs <- (char ',' >> spaces >> separated_numbers1) <|> option [] separated_numbers1 return (x : xs)
-- View this message in context: http://www.nabble.com/treating-spaces-with-Parsec-tp20857293p20895257.html Sent from the Haskell - Libraries mailing list archive at Nabble.com.
participants (2)
-
ben.a
-
Pixel