2017-03-31 5 views
0

私はC/C++/javaソースファイルを読み込み、ファイル全体に対して一連の変換を実行しようとしています。最初のフェーズは文字列を削除し、2番目のフェーズはコメントを削除します。Haskell:Parsec:ファイル全体のトランスフォーマーのパイプライン

各フェーズで文字列をいずれかの文字列に変換すると、(どちらの意味でも)それらを一緒にバインドして、変換のパイプラインを作りたいと思います。ファイル全体これはかなり一般的な要件のようです。

import Text.ParserCombinators.Parsec 

commentless, stringless :: Parser String 

stringless = fmap concat ((many (noneOf "\"")) `sepBy` quotedString) 
quotedString = (char '"') >> (many quotedChar) >> (char '"') 
quotedChar = try (string "\\\"" >> return '"') <|> (noneOf "\"") 

commentless = fmap concat $ notComment `sepBy` comment 
notComment = manyTill anyChar (lookAhead (comment <|> eof)) 
comment = (string "//" >> manyTill anyChar newline >> spaces >> return()) 
     <|> (string "/*" >> manyTill anyChar (string "*/") >> spaces >> return()) 


main = 
    do c <- getContents 
     case parse commentless "(stdin)" c of -- THIS WORKS 
--  case parse stringless "(stdin)" c of -- THIS WORKS TOO  
--  case parse (stringless `THISISWHATIWANT` commentless) "(stdin)" c of 
      Left e -> do putStrLn "Error parsing input:" 
         print e 
      Right r -> print r 

どうすればいいですか?私はparserBindを試したが、うまくいかなかった。

(なぜ誰かが気にしているのであれば、文法を解析したり、C++かJavaかどうかを知ることさえ避けています。すべてのクラスと関数の開始と終了の行番号ですので、#define/ifdefs、テンプレートのプリアンブルと括弧の内容(for節のセミコロンのため)を削除するだけの前処理フェーズを想定しています。どのようなものであれ、タイプと名前を取得するために、もう1つのフェーズでこれらのスニペットを詰め込んだ後、2番目のレベルに再帰してJavaメンバ関数を取得します。

答えて

2

Either Errorをバインドする必要があります。Parser。あなたはparse外のバインドを移動し、複数のparse Sを使用する必要があります。

parse stringless "(stdin)" input >>= parse commentless "(stdin)" 

あり、あなたが使っているものよりも優れたアプローチは、おそらくですが、これはあなたがやりたいだろう。

+0

これは機能しますが、少し厄介です。それをラップする演算子を書くことが可能なので、パース(文字列のない>>> commentless) "stdin"入力として書くことができますか? –

+0

do表記を使用できます。 – Lazersmoke

関連する問題