但是,我已经有一个非常强大的解析器,它可以为我做这件事。
它实际上不是那么健壮,你的解析器有多余括号的问题,它不会解析
((1) (2))
例如,它会在一些格式错误的输入上抛出异常,因为
singleP = Single . read <$> many digit
可以使用read "" :: Int
.
顺便说一句,优先级参数用于确定在某些地方是否需要括号,例如,如果你有
infixr 6 :+:
data a :+: b = a :+: b
data C = C Int
data D = D C
您不需要将括号括起来C 12
作为 的参数(:+:)
,因为应用程序的优先级高于 的(:+:)
,但是您需要将括号括起来C 12
作为 的参数D
。
所以你通常会有类似的东西
readsPrec p = needsParens (p >= precedenceLevel) someParser
wheresomeParser
解析输入中的值而不包含括号,并needsParens True thing
解析thing
括号之间的 a,同时needsParens False thing
解析thing
可选的括在括号中的 a [您应该始终接受比必要更多的括号,((((((1))))))
应该解析为Int
]。
由于readsPrec p
解析器用于在读取列表、元组等时将输入的部分解析为值的一部分,因此它们不仅必须返回解析的值,还必须返回输入的剩余部分。
parsec
这样,将解析器转换为解析器的简单方法readsPrec
是
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]
但是,如果您使用 GHC,则最好使用ReadPrec / ReadP
解析器(使用 构建Text.ParserCombinators.ReadP[rec]
)而不是parsec
解析器,并使用定义readPrec
而不是readsPrec
.