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

rlh*_*lhh 1 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 [])
Run Code Online (Sandbox Code Playgroud)

我试图解析为多个子中不包括字符的字符串'<','>'' '(空间),但我的解析器似乎并没有终止.有人可以给我一些关于我缺少的东西吗?

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

text :: Parser String 
text = manyL (sat textValid)
Run Code Online (Sandbox Code Playgroud)

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

parse (manyL text) "abc def <"
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 6

问题是manyL parser可以在不消耗输入的情况下成功(返回空列表).

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

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

你可能应该定义

text = many1L (sat textValid)
Run Code Online (Sandbox Code Playgroud)

使text不不消耗输入成功,大概是每个成功的解析后,为使用来自其他输入的开头空格是一个好主意,像

text = do
    result <- many1L (sat textValid)
    skipSpaces
    return result
Run Code Online (Sandbox Code Playgroud)

(skipSpaces左执行).