因此,我正在编写一个小型解析器,它将提取<td>
具有特定类的所有标签内容,例如这个<td class="liste">some content</td> --> Right "some content"
我将解析大html
文件,但是我并不真正在乎所有杂音,因此想法是消耗所有字符直到到达为止,而<td class="liste">
不是消耗所有字符(内容)直到</td>
返回内容字符串。
如果文件中的最后一个元素是我的td.liste
标签,则效果很好,但是如果我后面有一些文本,或者如果eof
我的解析器使用了它,unexpected end of input
则在执行时抛出该文本parseMyTest test3
。
-编辑
请参阅的结尾test3
以了解什么是边缘情况。
到目前为止,这是我的代码:
import Text.Parsec
import Text.Parsec.String
import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Char8 (pack)
colOP :: Parser String
colOP = string "<td class=\"liste\">"
colCL :: Parser String
colCL = string "</td>"
col :: Parser String
col = do
manyTill anyChar (try colOP)
content <- manyTill anyChar $ try colCL
return content
cols :: Parser [String]
cols = many col
test1 :: String
test1 = "<td class=\"liste\">Hello world!</td>"
test2 :: String
test2 = read $ show $ pack test1
test3 :: String
test3 = "\n\r<html>asdfasd\n\r<td class=\"liste\">Hello world 1!</td>\n<td class=\"liste\">Hello world 2!</td>\n\rasldjfasldjf<td class=\"liste\">Hello world 3!</td><td class=\"liste\">Hello world 4!</td>adsafasd"
parseMyTest :: String -> Either ParseError [String]
parseMyTest test = parse cols "test" test
btos :: ByteString -> String
btos = read . show
我创建了一个组合器skipTill p end
,该组合器将p
一直应用到end
匹配,然后返回返回的内容end
。
相反,manyTill p end
应用p
直到end
匹配,然后返回p
解析器匹配的内容。
import Text.Parsec
import Text.Parsec.String
skipTill :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m end
skipTill p end = scan
where
scan = end <|> do { p; scan }
td :: Parser String
td = do
string "("
manyTill anyChar (try (string ")"))
tds = do r <- many (try (skipTill anyChar (try td)))
many anyChar -- discard stuff at end
return r
test1 = parse tds "" "111(abc)222(def)333" -- Right ["abc", "def"]
test2 = parse tds "" "111" -- Right []
test3 = parse tds "" "111(abc" -- Right []
test4 = parse tds "" "111(abc)222(de" -- Right ["abc"]
更新
这似乎也起作用:
tds' = scan
where scan = (eof >> return [])
<|> do { r <- try td; rs <- scan; return (r:rs) }
<|> do { anyChar; scan }
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句