kaf*_*fka 2 parsing haskell parsec string-parsing
我正在使用parsec Haskell库.
我想解析以下类型的字符串:
[[v1]][[v2]]
xyz[[v1]][[v2]]
[[v1]]xyz[[v2]]
Run Code Online (Sandbox Code Playgroud)
等等
我很有意思只收集值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; };
}
}
Run Code Online (Sandbox Code Playgroud)
这样,如果输入"[[v1]][[v2]]"的程序工作正常,则返回以下输出:
"v1"
"v2"
Run Code Online (Sandbox Code Playgroud)
如果输入是"xyz[[v1]][[v2]]"程序不起作用.特别是,我只想要包含的内容[[...]],忽略"xyz".
另外,我想将内容存储[[...]]在数据结构中.
你怎么解决这个问题?
dfl*_*str 10
您需要重构解析器.你在非常奇怪的地方使用组合器,它们搞砸了.
A var是varName"[["和"]]之间的".所以写下:
var = between (string "[[") (string "]]") varName
Run Code Online (Sandbox Code Playgroud)
A varName应该有某种格式(我不认为你想接受"%A¤%&",对吗?),所以你应该为它做一个解析器; 但如果它真的可以是任何东西,只需这样做:
varName = many $ noneOf "]"
Run Code Online (Sandbox Code Playgroud)
然后,包含变量的文本是由非变量分隔的变量.
varText = someText *> var `sepEndBy` someText
Run Code Online (Sandbox Code Playgroud)
...... someText除了'['之外的任何地方:
someText = many $ noneOf "["
Run Code Online (Sandbox Code Playgroud)
如果你想要解析它,事情变得更复杂:
bla bla [ bla bla [[somevar]blabla]]
Run Code Online (Sandbox Code Playgroud)
然后你需要一个更好的解析器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 "["
Run Code Online (Sandbox Code Playgroud)
PS.(<*>),(*>)并且(<$>)是从Control.Applicative.