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、それがうまくいかない場合は、1文字食べてもう一度やり直してください。途中のすべてのがらくたを解析できますが (それが何であるかはわかっています)、それが何であるかは気にしません (だからわざわざ解析する​​必要があるのはなぜですか)。複雑になる可能性があります。

問題は、私の解決策がうまくいかないことです。anyCharすべてを消費することになり、検索にENDはチャンスがありません。また、どこかでcareAbout打っeofたりException、それが原因で投げたりすることもあります。

これはおそらくそれを行う正確な方法ではありません。私はそれを行う方法、またはさらに良い方法、Right Way™を知りたいと思っています。

4

2 に答える 2

2

パーサーでない場合、これはregex-applicativeparensなどの通常の言語パーサーに適しています。これは、通常の言語パーサーが「バックトラッキング」に関してはるかに「スマート」であるためです (実際、バックトラッキングはまったく行われていませんが、考えられるすべての分岐が調査されます)。

ただし、おそらくご存じのとおり、対応する括弧は通常の言語ではありません。文法を緩和して規則的にできる場合は、regex-applicative を試してみてください。

于 2013-09-23T06:50:38.147 に答える