
parseConstant = Reference <$> try parseLocLabel <|> PlainNum <$> decimal <|> char '#' *> fmap PlainNum hexadecimal <|> char '\'' *> (CharLit <$> notChar '\n') <* char '\'' <|> try $ (char '"' *> (StringLit . B.pack <$> manyTill (notChar '\n') (char '"'))) > "constant"
The problem is, that attoparsec just silently fails on this kind of strings and tries other parsers afterwards, which leads to strange results. Is there a way to force the whole parser to fail, even if there's an alternative parser afterwards?
If none of the alternatives consume any characters, then the next alternative will be tried. But this is a question for your grammar, i.e. it sounds like you have 'parseConstant <|> parseSomethingElse' and you want parseSomethingElse to not be tried? Then omit it! If your string parser isn't working how you want, I recommend breaking out the different kinds of literals, like chars and strings, and testing at the REPL to make sure they work on their own. BTW, if you use takeWhile you can avoid the extra pack. I like to use a between combinator: 'between a b mid = a >> mid <* b'. It's hard to read the applicative soup above, and I wouldn't trust it to be totally correct, instead I'd simplify with functions and test interactively. The 'try' is also redundant, I think.