[英]Parsing a particular string in Haskell
我正在使用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"
。
另外,我想將[[...]]
的內容存儲在數據結構中。
你怎么解決這個問題?
您需要重構解析器。 你在非常奇怪的地方使用組合器,它們搞砸了。
var
是“[[”和“]]”之間的varName
。 所以寫下:
var = between (string "[[") (string "]]") varName
varName
應該有某種格式(我不認為你想接受“%A¤%&”,對嗎?),所以你應該為它做一個解析器; 但如果它真的可以是任何東西,只需這樣做:
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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.