@Daniel Wagnerの答えを精緻化する...パーザは通常、Parsecで構築されますが、特定の文字(例:プラス記号や数字)を解析する低レベルのパーサから始め、上にパーサを構築します1つまたは複数の数字を読み取るパーサーに1桁の数字を読み取るパーサーを切り替えるコンビネーターや、「1つ以上の数字」の後ろに「プラス記号」が続く「モナドな解析」などのコンビネーターを使用して、 1つまたは複数の数字 ")。
ただし、各パーサーは、低レベルの桁パーサーでも高次の「加算式」パーサーでも、同じ入力ストリームに直接適用されることを意図しています。あなたは一般的にんが、たとえば、生成する入力ストリームのチャンクをゴブルズパーサを書くString
し、(代わりに、元の入力ストリームの)String
ことを解析し、別のパーサーとされていない何
それらを組み合わせてみてください。これは、Parsecによって直接サポートされていない "垂直構成"のようなもので、不自然でモナドではないように見えます。
としては、コメントで指摘した、縦組成物は(あなたが別の言語の要素や表現の中に埋め込まれた1つの言語を持っているときのように)きれいな全体的なアプローチですが、それが取られ、通常の方法ではありません一部状況がありますParsecパーサによって。
String
のみを生成するパーサーは、cell
パーサが役に立たないことがアプリケーションの最終行です。CSVファイルのためのより有用Parsecのフレームワークは、次のようになります。
今
import Text.Parsec
import Text.Parsec.String
-- | `csv cell` parses a CSV file each of whose elements is parsed by `cell`
csv :: Parser a -> Parser [[a]]
csv cell = many (row cell)
-- | `row cell` parses a newline-terminated row of comma separated
-- `cell`-expressions
row :: Parser a -> Parser [a]
row cell = sepBy cell (char ',') <* char '\n'
、あなたは正の整数を解析するカスタムセルパーサ書くことができます。
customCell :: Parser Int
customCell = read <$> many1 digit
をしてCSVファイルを解析:
> parse (csv customCell) "" "1,2,3\n4,5,6\n"
Right [[1,2,3],[4,5,6]]
>
ここでは、コンマ区切りのセルを明示的に解析して別のパーサーに送る文字列に変換するサブパラーを代わりに使用する代わりに、「セル」は暗黙のコンテキスト入力されたストリームの途中の行の途中でコンマで区切られたセルが必要となる適切なポイントで、基礎となる入力ストリームを解析するために呼び出されます。
私はあなたが垂直パーサの構成を意味するか分かりません。少し拡大してもらえますか? – gallais
@gallais私が求めているのは、「Parser Foo [Bar]」と「Parser Bar Baz」を「Parser Foo Baz」に変換する方法です。 –
ありがとうございます。このような単純なタイプでは、OPの質問よりもはるかに明確です。解明してくれてありがとう! – gallais