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 <waltaskew@gmail.com> wrote:
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