gpt4 book ai didi

haskell - parsec:意外字符解析嵌套注释

转载 作者:行者123 更新时间:2023-12-05 02:21:54 34 4
gpt4 key购买 nike

我正在尝试解析嵌套的类 C block 注释

import Text.ParserCombinators.Parsec
import Control.Monad (liftM)

flat :: Monad m => m [[a]] -> m [a]
flat = liftM concat

comment :: Parser String
comment = between (string "/*") (string "*/") (try nested <|> content)
where
content = many (try (noneOf "*/")
<|> try (char '*' >> notFollowedBy (char '/') >> return '*')
<|> try (char '/' >> notFollowedBy (char '*') >> return '/'))
nested = flat $ many comment

"1234567890" 解析正常,但是当我尝试时

parse comment "" "/*123/*456*/789*/"

我明白了

Left (line 1, column 3):
unexpected "1"
expecting "/*" or "*/"

我想不通为什么,我能想到的地方都有try。请帮忙。

最佳答案

在类似 a <|> b 的表达式中, 如果 a可以匹配空串然后b永远不会尝试,这发生在try nested <|> content .

您可以通过要求至少一个评论匹配或另一个字符来修正您的方法:

comment :: Parser String
comment = between (string "/*") (string "*/") ( flat $ many $ (try comment <|> liftM toString other ) )
where
toString x = [x]
other = try (noneOf "*/")
<|> try (char '*' >> notFollowedBy (char '/') >> return '*')
<|> try (char '/' >> notFollowedBy (char '*') >> return '/')

FWIW,这是如何Text.Parsec.Token这样做:

https://github.com/aslatter/parsec/blob/master/Text/Parsec/Token.hs#L698-714

对于您的特定情况,等效代码是:

import Data.List (nub)

commentStart = "/*"
commentEnd = "*/"

multiLineComment =
do { try (string commentStart)
; inComment
}

inComment = inCommentMulti

inCommentMulti
= do{ try (string commentEnd) ; return () }
<|> do{ multiLineComment ; inCommentMulti }
<|> do{ skipMany1 (noneOf startEnd) ; inCommentMulti }
<|> do{ oneOf startEnd ; inCommentMulti }
<?> "end of comment"
where
startEnd = nub (commentEnd ++ commentStart)

关于haskell - parsec:意外字符解析嵌套注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31646405/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com