html - 如何在 EOF 处停止 Haskell Parsec 解析器

标签 html parsing haskell parsec

所以,我正在编写一个小型解析器,它将提取所有 <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 }

关于html - 如何在 EOF 处停止 Haskell Parsec 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38982992/

相关文章:

html - 使用 :target 更改多个元素的 CSS

javascript - Flex Box 未按预期运行

html - 完全加载后播放html5视频

java - Scala 将很长的字符串解析为日期

mysql - 将 PAF 文件导入 MySQL

Python 从 URL 字符串中解析单词

user-interface - 函数式 GUI 编程可能吗?

html - 在移动设备上浏览我的页面时出现 Z-index 问题

haskell - 模式同义词作为函数的无趣/困惑

树上的haskell折叠操作