您可以从attoparsec获取当前解析位置,而无需转换器。但是没有导出函数可以做到这一点;你必须自己定义它:
import qualified Data.Attoparsec.Internal.Types as T
offset :: T.Parser i T.Pos
offset = T.Parser $ \t pos more lose succ -> succ t pos more pos
示例用法:
λ> parseOnly (many' (skipMany (word8 46) *> offset <* anyWord8)) ".a..a...a....a"
Right [Pos {fromPos = 1},Pos {fromPos = 4},Pos {fromPos = 8},Pos {fromPos = 13}]
这对于增量输入也可以按预期工作。它只为您提供输入的偏移量,而不是(line, column)
,但对于许多应用程序来说,偏移量就足够了。
用于从 afromPos
获取:Int
Pos
λ> T.fromPos <$> parseOnly offset ""
Right 0
现在,我们可以使用offset
创建一个解析器,当它失败时报告当前偏移量。
reportOffsetOnError :: T.Parser i a -> T.Parser i a
reportOffsetOnError p =
p <|> (offset >>= \pos ->
fail ("failed at offset: " ++ show (T.fromPos pos)))
示例用法:
λ> parseOnly (word8 46 *> word8 46 *> reportOffsetOnError (word8 97)) "..a"
Right 97
λ> parseOnly (word8 46 *> word8 46 *> reportOffsetOnError (word8 97)) "..b"
Left "Failed reading: failed at offset: 2"
最后一点:如果你真的需要一个转换器并且想继续使用attoparsecData.Attoparsec.Zepto
包,它确实提供了转换器,但这是与 attoparsec 中的主解析器不同的解析器类型。ZeptoT