我正在使用parsec Haskell库。
我想解析以下类型的字符串:
[[v1]][[v2]]
xyz[[v1]][[v2]]
[[v1]]xyz[[v2]]
等
我很有兴趣只收集值v1和v2,并将它们存储在数据结构中。
我尝试使用以下代码:
import Text.ParserCombinators.Parsec
quantifiedVars = sepEndBy var (string "]]")
var = between (string "[[") (string "") (many (noneOf "]]"))
parseSL :: String -> Either ParseError [String]
parseSL input = parse quantifiedVars "(unknown)" input
main = do {
c <- getContents;
case parse quantifiedVars "(stdin)" c of {
Left e -> do { putStrLn "Error parsing input:"; print e; };
Right r -> do{ putStrLn "ok"; mapM_ print r; };
}
}
这样,如果输入为"[[v1]][[v2]]"
,程序运行正常,返回以下输出:
"v1"
"v2"
如果输入为"xyz[[v1]][[v2]]"
,则程序不起作用。特别是,我只想要[[...]]
中包含的内容,忽略"xyz"
。
另外,我想将[[...]]
的内容存储在数据结构中。
你如何解决这个问题?
答案 0 :(得分:10)
您需要重新构建解析器。你在非常奇怪的地方使用组合器,它们搞砸了。
var
是“[[”和“]]之间的varName
。所以,写下:
var = between (string "[[") (string "]]") varName
varName
应该有某种格式(我不认为你想接受“%A¤%&amp;”,是吗?),所以你应该为它做一个解析器;但如果它确实可以是任何东西,那就这样做:
varName = many $ noneOf "]"
然后,包含变量的文本是由非变量分隔的变量。
varText = someText *> var `sepEndBy` someText
...其中someText
除了'[':
someText = many $ noneOf "["
如果你想让它变得可解析,事情会变得更复杂:
bla bla [ bla bla [[somevar]blabla]]
然后,您需要更好的解析器varName
和someText
:
varName = concat <$> many (try incompleteTerminator <|> many1 (noneOf "]"))
-- Parses e.g. "]a"
incompleteTerminator = (\ a b -> [a, b]) <$> char ']' <*> noneOf "]"
someText = concat <$> many (try incompleteInitiator <|> many1 (noneOf "["))
-- Parses e.g. "[b"
incompleteInitiator = (\ a b -> [a, b]) <$> char '[' <*> noneOf "["
<强> PS 即可。 (<*>)
,(*>)
和(<$>)
来自Control.Applicative
。