解析Haskell中的特定字符串

时间:2012-02-14 14:24:10

标签: parsing haskell string-parsing parsec

我正在使用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"

另外,我想将[[...]]的内容存储在数据结构中。

你如何解决这个问题?

1 个答案:

答案 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]]

然后,您需要更好的解析器varNamesomeText

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