Haskell“解析”不会终止特定类型的字符串

时间:2013-04-24 18:52:32

标签: haskell xml-parsing

parse' :: Parser a -> String -> [(a,String)]
parse' p inp = p `with` inp

parse :: Parser a -> String -> [a]
parse p inp = [ v | (v,[]) <- parse' p inp ]

mkMany1 :: (Parser a -> Parser [a]) -> Parser a -> Parser [a]
mkMany1 many p = do x <- p
                    xs <- many p
                    return (x:xs)

many1L :: Parser a -> Parser [a]
many1L = mkMany1 manyL

manyL :: Parser a -> Parser [a]
manyL p = (many1L p) ||| (success [])

我正在尝试为不包含字符'<''>'' '(空格)的多个子字符串解析字符串,但我的解析器看起来不像终止。有人可以给我一些关于我缺少的东西吗?

textValid :: Char -> Bool
textValid c =  c /= '<' && c /= '>' && not (isSpace c)      

text :: Parser String 
text = manyL (sat textValid)

当我尝试运行以下命令时,它永远不会终止。

parse (manyL text) "abc def <"

1 个答案:

答案 0 :(得分:6)

问题是manyL parser可以成功而不消耗输入(返回空列表)。

一个人不能传递一个可以成功的解析器,而不会消耗输入作为manyL的参数,因为在这种情况下,你会得到你所处的无限循环。

在第一个text消费输入的"abc"前缀后,您将留下" def <"一个以String开头的空格。因此,尝试使用text时,它会消耗尽可能多的textValid字符,而不是String的开头 - 即0 - 并返回它们 - []。留下相同的输入。现在manyL text再次尝试text,看看是否也成功了......

你应该定义

text = many1L (sat textValid)

这样text在没有消耗输入的情况下不会成功,并且在每次成功解析后从剩余输入的开头消耗空格可能是个好主意,比如

text = do
    result <- many1L (sat textValid)
    skipSpaces
    return result

skipSpaces离开实施)。