2012-02-14 10 views
2

私はparsec Haskellライブラリを使用しています。私は、次のような文字列を解析したいHaskellでの特定の文字列の解析

[[v1]][[v2]] 

xyz[[v1]][[v2]] 

[[v1]]xyz[[v2]] 

など

私は唯一の値v1と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" 

入力が"xyz[[v1]][[v2]]"ある場合プログラムが動作しません。特に、私は[[...]]に含まれているものだけを、"xyz"を無視して欲しいです。

また、[[...]]の内容をデータ構造に保存したいとします。

この問題をどうやって解決しますか?

+0

'[['と ']]'で区切られていないものはスキップしますか? xyz [[v1]] [[v2]] "'と[[[v1]] xyz [[v2]] "はどちらも' ["v1"、 "v2"] 'を返すでしょうか? –

+0

正規表現では簡単な作業のようです。 \\ [\\ [([^]] +)\\] \\] ' – Yuras

答えて

10

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

varは、[["と"]]の間にvarNameです。だから、それを書く:

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

varNameあなたはパーサを作る必要がありますので、フォーマットのいくつかの種類(私は、あなたが「%のA¤%の&」を受け入れるようにしたいとは思わないのですか?)が必要ですそれのために。しかし、場合には、それは本当に、何もすることができちょうどこの操作を行います。

varName = many $ noneOf "]" 

その後、VARSを含むテキストは、非VARSで区切られたVARSで何かです。あなたは、これが解析可能にしたい場合は

someText = many $ noneOf "[" 

物事は複雑になります::

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

次に、必要なsomeTextは、 '[' 以外のものである

varText = someText *> var `sepEndBy` someText 

... 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である。

+0

親愛なるdflemstrさん、非常に詳細な回答をありがとうございます。私はあなたのソリューションを実装しようとしましたが、 "Text.ParserCombinators.Parsec"とともにライブラリ "Control.Applicative"をインポートするあいまいさの問題がありました。特に、 "あいまいなオカレンス" many "..." "あいまいなオカレンス" <|> '... "。だから、私は "隠し((<|>)、多く)"を使用しようとしましたが、ghcは新しいエラーを返します。この問題をどうやって解決しますか?ありがとう! – kafka

+1

それは私がそれをする方法です。代わりに 'import Control.Applicative((<*>)、(*>)、(<$>))'を実行してみてください。 – dflemstr