
I am trying to use parsec to turn strings like this: “#newch The Period #txt It was the best of times #newpar #txt it was the worst of times” into data structures like this: [NewChapter “The Period”, Text "It was the best of times”, NewParagraph, Text "it was the worst of times”] My current attempt returns this, however: [NewChapter "The Period "] That is, my current implementation only parses out the first item in the string and does not find the remaining items. I’m not sure why that is. I’d suspect I am misusing parsec’s “many” or “manyTill” somehow, but it isn’t clear to me why my use of “many" results in only single item lists. My code is pasted below — any suggestions? This is my first exploration of parsec, so any general suggestion on using the library are welcome (for instance, I do note that I end up double-parsing the strings “#newch, #txt and #newpar because both nextCommand and the newChapter newText and newPar parsers all parse those same strings, but I’m not sure how to avoid that elegantly.) Thanks for your help! parser = many command command = newChapter <|> newTxt <|> newPar newChapter = do try (string "#newch") spaces chapterName <- text return (NewChapter chapterName) newTxt = do try (string "#txt") spaces content <- text return (Text content) newPar = do try (string "#newpar") spaces return NewParagraph text = manyTill anyChar nextCommand nextCommand = try (string "#newch") <|> try (string "#txt") <|> try (string "#newpar") <|> eof *> return ""

First, when you post something like this, please put enough code to at
least compile. I had to spend five minutes adding some code to make this
compile.
The reason it doesn't work is your manyTill anyChar nextCommand. In this
case nextCommand actually slurps up the next hashtag, leaving you
positioned at " It was ...", then you try to match another command, and it
fails, and terminates.
The fix is simple, you just have to prevent it from eating the next tag you
intended to stop at, which you can do by changing it to manyTill anyChar
(lookAhead nextCommand)
On Tue, May 6, 2014 at 2:54 PM, Walter Askew
I am trying to use parsec to turn strings like this:
“#newch The Period #txt It was the best of times #newpar #txt it was the worst of times”
into data structures like this:
[NewChapter “The Period”, Text "It was the best of times”, NewParagraph, Text "it was the worst of times”]
My current attempt returns this, however:
[NewChapter "The Period "]
That is, my current implementation only parses out the first item in the string and does not find the remaining items. I’m not sure why that is. I’d suspect I am misusing parsec’s “many” or “manyTill” somehow, but it isn’t clear to me why my use of “many" results in only single item lists.
My code is pasted below — any suggestions? This is my first exploration of parsec, so any general suggestion on using the library are welcome (for instance, I do note that I end up double-parsing the strings “#newch, #txt and #newpar because both nextCommand and the newChapter newText and newPar parsers all parse those same strings, but I’m not sure how to avoid that elegantly.)
Thanks for your help!
parser = many command
command = newChapter <|> newTxt <|> newPar
newChapter = do try (string "#newch") spaces chapterName <- text return (NewChapter chapterName)
newTxt = do try (string "#txt") spaces content <- text return (Text content)
newPar = do try (string "#newpar") spaces return NewParagraph
text = manyTill anyChar nextCommand
nextCommand = try (string "#newch") <|> try (string "#txt") <|> try (string "#newpar") <|> eof *> return "" _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

First, when you post something like this, please put enough code to at least compile. I had to spend five minutes adding some code to make this compile.
Sorry about that, but thank you very much for your help!
The reason it doesn't work is your manyTill anyChar nextCommand. In this case nextCommand actually slurps up the next hashtag, leaving you positioned at " It was ...", then you try to match another command, and it fails, and terminates.
Thanks, that makes sense. I was foolishly looking at the try’s in nextCommand, imagining that they would solve all of my look ahead problems and apparently forgetting they gobble input on success. Thanks again!
participants (2)
-
David McBride
-
Walter Askew