個々のパーサは単独では余り利用価値がない。パーサを組み合わせることで多様なパターンに対応できる。組み合わせかたの「くりかえし」については前回に述べた。この記事では、パターンの連接と選択について調べてみる。
Parsec で使われる要素的なパーサは Parsec モナドの関数だ。IOモナドの時と同じように、モナドの関数を合成してもそれはやはりそのモナドの関数になる。つまり、Parsec モナドの関数であるパーサを合成してもやはり、Parsec モナドの関数つまりパーサになるということだ。 たとえば、(many letter) という関数はアルファベットの文字列のパーサだ。また、(many digit) というのは、数字の列のパーサだ。この2つを使って、文字列の次に数字の列が来るようなパターンにマッチするパーサを組み立てたいときはどうすればいいだろうか。このようなパターンの連接(並び)を作るには、モナドの do 記法を使う。そこで、次のような alnum という新しいパーサを定義してみる。 Prelude> :m Text.ParserCombinators.Parsec Prelude Text.ParserCombinators.Parsec> let alnum = do many letter; many digit Prelude Text.ParserCombinators.Parsec> parseTest alnum "hello123 world" "123" 上の例では確かにマッチしているが、戻値は後半のマッチだけだ。マッチの全体を戻値として得るためには、alnum を次のように定義すればいい。 Prelude Text.ParserCombinators.Parsec> let alnum = do a <- many letter; b <- many digit; return (a ++ b) Prelude Text.ParserCombinators.Parsec> parseTest alnum "hello123 world" "hello123" Parsec のパターンマッチのうれしいところは、Perl では正規表現が言語内言語として使用されているのに対し、あくまでも Haskell で記述できるということだ。上のような細かい調整が、Haskell で記述できるので新しい言語を覚える必要がない。 それでは、(many letter) または (many digit) にマッチするパーサを作ってみよう。 Prelude Text.ParserCombinators.Parsec> let alOrNum = many1 letter <|> many1 digit Prelude Text.ParserCombinators.Parsec> parseTest alOrNum "123hello" "123" パターンの選択の場合はパーサを <|> 演算子で結合するとよいことが分かる。 これで、Parsec を使ってパターンマッチを使うプログラムの作り方に関する記事は終わりだ。 最後に、Parsec によるパターンマッチを使ったサンプルプログラム match_test を紹介する。*.hs ファイルの中から = 記号を見つけて関数の名前をリストアップするプログラムだ。以前に紹介した Match.hs を利用する。コンパイルは ghc --make mathc_test.hs -o match_test で行う。 実行例: >match_test Match.hs match expr line = getMatch expr line = ソースファイルは次のようになる。 ファイル名: match_test.hs module Main where import Text.ParserCombinators.Parsec import Match import System.Environment (getArgs) concatFile :: [FilePath] -> IO [Char] concatFile [] = return [] concatFile (f:fs) = do xs <- readFile f rest <- concatFile fs return $ xs ++ rest func_def = manyTill anyChar (char '=') main = do args <- getArgs cs <- if null args then getContents else concatFile args putStrLn $ unlines $ filter (match func_def) $ lines cs
by tnomura9
| 2011-11-27 19:27
| Haskell
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||