使用Parsec搜索模式

时间:2013-09-23 03:08:10

标签: haskell parsec

不确定这是否可行(或推荐),但我实际上是在尝试使用Parsec在文件中搜索一系列字符。示例文件:

START (name)

junk
morejunk=junk;
dontcare
    foo ()
    bar

care_about this (stuff in here i dont care about);

don't care about this
or this
foo = bar;

also_care
about_this
(dont care whats in here);
and_this too(only the names
   at the front
   do i care about
);

foobar
may hit something = perhaps maybe (like this);
foobar

END

以下是我尝试让它发挥作用:

careAbout :: Parser (String, String)
careAbout = do
    name1 <- many1 (noneOf " \n\r")
    skipMany space
    name2 <- many1 (noneOf " (\r\n")
    skipMany space
    skipMany1 parens
    skipMany space
    char ';'
    return (name1, name2)

parens :: Parser ()
parens = do
    char '('
    many (parens <|> skipMany1 (noneOf "()"))
    char ')'
    return ()

parseFile = do
    manyTill (do
        try careAbout <|>
        anyChar >> return ("", "")) (try $ string "END")

我试图通过查找careAbout来强制搜索,如果这不起作用,请吃一个字符再试一次。我可以解析中间的所有垃圾(我知道它可能是什么),但我不关心它是什么(所以为什么还要解析它),而且它可能很复杂。

问题是,我的解决方案不太有效。 anyChar最终消耗了所有内容,搜索END永远不会有机会。此外,careAbout中的某个地方我们点击了eof,而某些Exception因此被抛出。

这可能是完全错误的做法,我想知道 a 方式,甚至更好的方法,也就是Right Way™。

2 个答案:

答案 0 :(得分:1)

如果不是parens解析器,这将非常适合常规语言解析器,例如regex-applicative。这是因为常规语言解析器对于“回溯”更加“聪明”(实际上根本没有回溯,但是每个可能的分支都被探索过。)

但是,您可能知道,匹配的括号不是常规语言。如果你可以放松你的语法成为常规,试试一下regex-applicative。

答案 1 :(得分:0)

我不能从OP的帖子中真正分辨出我们关心文件的哪个部分,或者 不,所以我不会发布特定的解决方案。但总的来说, 在文件中搜索与递归解析器匹配的模式 可以使用 replace-megaparsec