wvogel日記

自分用の技術備忘録が多めです.

Parsec.Expr

うう......
Parsecいじっていたけれど、やはりいきなり書き始めるのはなかなかに辛いものがある。
ということで

http://www.lab2.kuis.kyoto-u.ac.jp/~hanatani/tmp/Parsec.html
にあるサンプルソースコードを読んでまずは流れを理解することにする。

module Parsing where

import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr

expr :: Parser Integer
expr = buildExpressionParser table factor
        <?> "expression"

table = [[op "*" (*) AssocLeft, op "/" div AssocLeft]
          ,[op "+" (+) AssocLeft, op "-" (-) AssocLeft]]
        where
          op s f assoc
             = Infix (do{ string s; return f}) assoc

factor = do{ char '('
            ; x <- expr
            ; char ')'
            ; return x
            }
        <|> number
        <?> "simple expression"

number :: Parser Integer
number = do{ ds <- many1 digit
            ; return (read ds)
            }
        <?> "number"

モナドのいいところは、現在その関数内で扱っているデータを表面から見えないように隠蔽してやることが出来る点ですかね
それによって、意識せずとも関数の機能に重きがおかれる
しかし、それによって、まだモナドになれていない人が読むには辛い部分もあったり。
上の関数個々の機能はわかるんですけどね。
これを書けるかといわれたら.....
しかし、前私がParsec使わずに書いた括弧なし計算のソースコードと比べてもとても簡潔に書かれている.....
Parsec使わずとも、リストの文字列処理だけでパーサもレクサーも一応作れるけれど、
標準でこれだけ強力なパーサライブラリがあるのだから使わないと損だろう。
それに格段に短く、整理して書けるというのは、それだけでもやはり学んでおきたいなと思います
しかし難しい.....
とりあえずXMLとか読めるか取り組んでみることにしようか。
でもなあ。
それじゃあ前作ったレクサーとやってること一緒だよな......
なんか面白い題材ないかなー。
数字列から二分探索木を生成するとか?



モナドは単なる型クラスに過ぎないと言われたらそうなんだけど、扱いになれるまではやはり自分では書きづらい。
他人の書いたコードは読めるようにはなってきた。