7

不确定这是否可能(或推荐),但我实际上是在尝试使用 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人因此而被抛出。

这可能是完全错误的方法,我想知道一种方法,甚至更好,正确的方法™,这样做。

4

2 回答 2

2

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

但是,您可能知道,匹配括号不是常规语言。如果您可以放松您的语法以变得有规律,请尝试使用 regex-applicative。

于 2013-09-23T06:50:38.147 回答
0

我无法从 OP 的帖子中真正看出我们关心或不关心文件的哪些部分,所以我不会发布具体的解决方案。但一般来说,要在文件中搜索与递归解析器匹配的模式,可以使用 replace-megaparsec

于 2019-09-05T13:00:14.003 回答