However, I already have a very strong parser that does this for me.
Actually, itβs not so cool that your parser has problems with extra parentheses, it will not parse
((1) (2))
and it will throw an exception on some distorted inputs because
singleP = Single . read <$> many digit
may use read "" :: Int .
In this case, the priority argument is used to determine whether the brackets are needed anywhere, for example. if you have
infixr 6 :+: data a :+: b = a :+: b data C = C Int data D = DC
you do not need parentheses around C 12 as an argument (:+:) , since the application priority is higher than that of (:+:) , but you need parentheses around C 12 as an argument D
So you usually have something like
readsPrec p = needsParens (p >= precedenceLevel) someParser
where someParser parses the value from input without conclusions in parentheses, and needsParens True thing parses a thing between parentheses, and needsParens False thing parses thing , optionally enclosed in parentheses [you should always take more brackets than necessary, ((((((1)))))) should be disassembled as Int ].
Since readsPrec p analyzers readsPrec p used to parse input parts as parts of a value when reading lists, tuples, etc., they should return not only the parsed value, but also the rest of the input.
So an easy way to convert a parsec parser to a readsPrec parser would be
withRemaining :: Parser a -> Parser (a, String) withRemaining p = (,) <$> p <*> getInput parsecToReadsPrec :: Parser a -> Int -> ReadS a parsecToReadsPrec parsecParser prec input = case parse (withremaining $ needsParens (prec >= threshold) parsecParser) "" input of Left _ -> [] Right result -> [result]
If you use GHC, it might be preferable to use the ReadPrec / ReadP (built using Text.ParserCombinators.ReadP[rec] ) instead of the parsec parser and define readPrec instead of readsPrec .