如何获取解析中读取的字符数?



我正在使用Numeric.readDec来解析数字,并使用reads来解析字符串。但我也需要知道读了多少个字符。

例如,readDec "52 rest"返回[(52," rest")]并读取 2 个字符。但是我找不到一种很好的方法来知道它读取了 2 个字符。

您可以检查show 52的字符串长度,但如果输入是 052,则会给您错误的答案(此解决方案也不适用于具有转义字符的字符串解析)。您还可以使用从输入字符串的长度中减去后解析字符串的长度。但对于具有许多解析的长字符串来说,这是非常低效的。

如何正确有效地完成此操作(最好不要只编写自己的解析)?

只需base,而不是readDec,您就可以使用Text.Read.Lex中的readDecP,它使用ReadP解析器:

readDecP :: (Eq a, Num a) => ReadP a

Text.ParserCombinators.ReadP中的gather组合器返回解析结果以及解析的实际字符:

gather :: ReadP a -> ReadP (String, a)

您可以使用readP_to_S运行解析器,这将返回一个ReadS解析器,该解析器是一个接受字符串并使用字符串的其余部分生成可能解析列表的函数。

readP_to_S :: ReadP a -> ReadS a
type ReadS a = String -> [(a, String)]

GHCi 中的一个例子:

> import Text.ParserCombinators.ReadP (gather, readP_to_S)
> import Text.Read.Lex (readDecP)
> readP_to_S (gather readDecP) "52 rest"
[(("52",52)," rest")]
> readP_to_S (gather readDecP) "0644 permissions"
[(("0644",644)," permissions")]

如果您希望结果明确,您可以简单地检查只有一个有效的解析,然后取第一个组件的长度来查找解析的Char代码点的数量。

然而,这些解析器相当有限;如果你想要一些更易于使用、更快或能够产生更详细的错误消息的东西,那么你应该查看一个功能更齐全的解析包,如regex-applicative(常规语法)或megaparsec(上下文相关语法)。

最新更新