【发布时间】:2020-06-26 00:08:57
【问题描述】:
考虑这些不同的解析器组合器的用法。
import Control.Applicative.Combinators
import Text.Regex.Applicative
main :: IO ()
main = do
let parser1 = sym '"' *> manyTill anySym (sym '"')
print $ match parser1 "\"abc\""
let parser2 = sym '"' *> many anySym <* sym '"'
print $ match parser2 "\"abc\""
import Control.Applicative.Combinators
import Text.ParserCombinators.ReadP hiding(many, manyTill)
main :: IO ()
main = do
let parser1 = char '"' *> manyTill get (char '"')
print $ readP_to_S parser1 "\"abc\""
let parser2 = char '"' *> many get <* char '"'
print $ readP_to_S parser2 "\"abc\""
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative.Combinators
import Data.Attoparsec.Text hiding(manyTill)
main :: IO ()
main = do
let parser1 = char '"' *> manyTill anyChar (char '"')
print $ parseOnly parser1 "\"abc\""
let parser2 = char '"' *> many anyChar <* char '"'
print $ parseOnly parser2 "\"abc\""
import Control.Applicative.Combinators
import Text.Megaparsec hiding(many, manyTill)
import Data.Void
main :: IO ()
main = do
let parser1 = single '"' *> manyTill anySingle (single '"') :: Parsec Void String String
print $ parseMaybe parser1 "\"abc\""
let parser2 = single '"' *> many anySingle <* single '"' :: Parsec Void String String
print $ parseMaybe parser2 "\"abc\""
对于这四个,manyTill 解析器成功匹配abc,因为这不依赖于回溯。使用regex-applicative 和ReadP,many 解析器也成功匹配abc,因为它们都默认回溯。使用megaparsec,many 解析器无法匹配,因为默认情况下它不会回溯。到目前为止,一切都说得通。然而,使用attoparsec,many 解析器无法匹配,即使它确实回溯:its documentation 说“attoparsec 解析器总是在失败时回溯”和“如果您将增量输入提供给解析器,它将需要内存与您提供的输入量成正比。(这是支持任意回溯所必需的。)“。为什么是这样?回溯不应该就是这样吗?
【问题讨论】:
标签: parsing haskell backtracking parser-combinators attoparsec