我正在努力解析Google 项目 wiki 语法Parsec
的一小部分,并将其转换为 HTML。我的语法仅限于文本序列和项目列表。这是我想要识别的示例:
Text that can contain any kind of characters,
except the string "\n *"
* list item 1
* list item 2
End of list
到目前为止,我的代码是:
import Text.Blaze.Html5 (Html, toHtml)
import qualified Text.Blaze.Html5 as H
import Text.ParserCombinators.Parsec hiding (spaces)
parseList :: Parser Html
parseList = do
items <- many1 parseItem
return $ H.ul $ sequence_ items
parseItem :: Parser Html
parseItem = do
string "\n *"
item <- manyTill anyChar $
(try $ lookAhead $ string "\n *") <|>
(try $ string "\n\n")
return $ H.li $ toHtml item
parseText :: Parser Html
parseText = do
text <- manyTill anyChar $
(try $ lookAhead $ string "\n *") <|>
(eof >> (string ""))
return $ toHtml text
parseAll :: Parser Html
parseAll = do
l <- many (parseUl <|> parseText)
return $ H.html $ sequence_ l
应用于parseAll
任何字符序列时,我收到以下错误消息:"*** Exception: Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string.
我知道这是因为我的解析器parseText
可以读取空字符串,但我看不到任何其他方式。如何识别由字符串分隔的文本?("\n *"
这里)。
我也愿意接受有关我使用 Parsec 的方式的任何评论或建议。我不禁看到我的代码有点难看。我能以更简单的方式完成这一切吗?例如,由于 string 存在代码复制(这有点痛苦)"\n *"
,用于识别文本序列的结尾、列表项的开头和列表项的结尾......