首页 > 解决方案 > 如何在解析中还读取多少个字符?

问题描述

Numeric.readDec用来解析数字和reads解析字符串。但我还需要知道读取了多少个字符。

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

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

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

标签: parsinghaskell

解决方案


使用 just base,而不是readDec,您可以使用readDecPfrom Text.Read.Lex,它使用ReadP解析器:

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

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

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(regular grammars) 或megaparsec(context-sensitive grammars)。


推荐阅读