如果我想要将包含表单~{content}注释的字符串解析为Comment记录,那么我将如何处理?例如:
data Comment = { id :: Integer, content :: String }
parse :: Parser [Comment]
parse = _
parse
"hello world ~{1-sometext} bla bla ~{2-another comment}"
== [Comment { id = 1, content = "sometext" }, Comment { id = 2, content = "another comment"}]我所坚持的是允许忽略所有非~{}的内容,包括单独的char ~和唯一的方括号{}。
发布于 2022-11-02 16:34:34
您可以这样做:将字符拖到下一个倾斜点,然后可选地解析该倾斜符,后面跟着一个有效的注释,然后循环。
特别是,如果我们将nonTildes定义为丢弃非倾斜体:
nonTildes :: Parser String
nonTildes = takeWhileP (Just "non-tilde") (/= '~')然后是一个optionalComment,用于在大括号中解析一个倾斜的和可选的注释:
optionalComment :: Parser (Maybe Comment)
optionalComment = char '~' *>
optional (braces (Comment <$> ident_ <* char '-' <*> content_))
where
braces = between (char '{') (char '}')
ident_ = read <$> takeWhile1P (Just "digit") isDigit
content_ = takeWhileP Nothing (/= '}')然后,这些注释可以用以下内容进行解析:
comments :: Parser [Comment]
comments = catMaybes <$> (nonTildes *> many (optionalComment <* nonTildes))这假设没有匹配的~{是一个解析错误,而不是有效的非注释文本,这似乎是明智的。但是,content_解析器的定义可能过于宽松。它吞噬了所有的东西,直到下一个},这意味着:
"~{1-{{{\n}"是带有内容"{{{\n"的有效注释。在注释中不允许{ (或者~),或者要求大括号正确地嵌套在注释中似乎是个好主意。
总之,这里有一个完整的代码示例供您使用:
{-# OPTIONS_GHC -Wall #-}
import Data.Char
import Data.Maybe
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
type Parser = Parsec Void String
data Comment = Comment { ident :: Integer, content :: String } deriving (Show)
nonTildes :: Parser String
nonTildes = takeWhileP (Just "non-tilde") (/= '~')
optionalComment :: Parser (Maybe Comment)
optionalComment = char '~' *>
optional (braces (Comment <$> ident_ <* char '-' <*> content_))
where
braces = between (char '{') (char '}')
ident_ = read <$> takeWhile1P (Just "digit") isDigit
content_ = takeWhileP Nothing (/= '}')
comments :: Parser [Comment]
comments = catMaybes <$> (nonTildes *> many (optionalComment <* nonTildes))
main :: IO ()
main = do
parseTest comments "hello world ~{1-sometext} bla bla ~{2-another comment}"
parseTest comments "~~~ ~~~{1-sometext} {junk}"https://stackoverflow.com/questions/74287406
复制相似问题