2

私は 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"

[[...]]また、コンテンツをデータ構造に保存したいと考えています。

この問題をどのように解決しますか?

4

1 に答える 1

10

パーサーを再構築する必要があります。非常に奇妙な場所でコンビネータを使用しており、物事を台無しにしています。

AvarvarName"[[" と "]]" の間です。だから、それを書いてください:

var = between (string "[[") (string "]]") varName

AvarNameには何らかの形式が必要なので (「%A¤%&」を受け入れたくないと思いますよね?)、そのためのパーサーを作成する必要があります。しかし、それが本当に何でもよい場合は、次のようにしてください。

varName = many $ noneOf "]"

次に、変数を含むテキストは、非変数で区切られた変数を持つものです。

varText = someText *> var `sepEndBy` someText

... someText「[」以外はどこですか:

someText = many $ noneOf "["

これを解析可能にしたい場合、事態はさらに複雑になります。

bla bla [ bla bla [[somevar]blabla]]

varName次に、 andのより優れたパーサーが必要です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 "["

PS(<*>)(*>)から(<$>)ですControl.Applicative

于 2012-02-14T15:07:57.930 に答える