I'm learning Parsec. I've got this code:
import Text.Parsec.String (Parser)
import Control.Applicative hiding ((<|>))
import Text.ParserCombinators.Parsec hiding (many)
inBracketsP :: Parser [String]
inBracketsP = (many $ between (char '[') (char ']') (many $ char '.')) <* eof
main :: IO ()
main = putStr $ show $ parse inBracketsP "" "[...][..."
The result is
Left (line 1, column 10):
unexpected end of input
expecting "." or "]"
This message is not useful (adding .
won't fix the problem). I'd expect something like ']' expected
(only ]
fixes the problem).
Is it possible to achieve that easily with Parsec? I've seen the SO question Parsec: error message at specific location, which is inspiring, but I'd prefer to stick to the between
combinator, without manual lookahead or other overengineering (kind of), if possible.
CodePudding user response:
You can hide a terminal from being displayed in the expected input list by attaching an empty label to it (parser <?> ""
):
inBracketsP :: Parser [String]
inBracketsP = (many $ between (char '[') (char ']') (many $ (char '.' <?> ""))) <* eof
-- >>> main
-- Left (line 1, column 10):
-- unexpected end of input
-- expecting "]"
In megaparsec
, there is also a hidden
combinator that achieves the same effect.