第8章 関数型パーサー #4

旅行に行ったので間があいてしまった。

数式

相変わらずdo記法を使わずにオレオレbindとオレオレreturnで書いてみる。

expr :: Parser Int
expr  = term >>- \t ->
        (symbol "+" >>- \d ->
         expr >>- \e ->
         return' (t + e))
        +++ return' t

term :: Parser Int
term  = factor >>- \f ->
        (symbol "*" >>- \d ->
         term >>- \t ->
         return' (f * t))
        +++ return' f

factor :: Parser Int
factor  = (symbol "(" >>- \d1 ->
           expr >>- \e ->
           symbol ")" >>- \d2 ->
           return' e)
          +++ natural

eval :: String -> Int
eval xs = case parse expr xs of
            [(n,[])]  -> n
            [(_,out)] -> error ("unused input " ++ out)
            []        -> error "invalid input"

練習問題

問題1

symbolにしたけどcharでもよかったな。

int :: Parser Int
int  = (symbol "-" >>- \d ->
        natural >>- \n ->
        return' (-n))
       +++ natural

問題2

1行読んで無視するlineを定義してみた。

comment :: Parser ()
comment  = string "--" >>- \d1 ->
           line
           where
             line = item >>- \x ->
                    case x of
                      '\n' -> return' ()
                      _    -> line

問題3

1個目

           expr
     _______|___
     |      |  |
    expr    + expr
 ____|___      |
 |   |  |     term
expr + expr    |
 |      |     factor
term   term    |
 |      |     nat
factor factor  |
 |      |      4
nat    nat
 |      |
 2      3

2個目

    expr
 ____|_______
 |   |      |
expr +     expr
 |      ____|___
term    |   |  |
 |     expr + expr
factor  |      |
 |     term   term
nat     |      |
 |     factor factor
 2      |      |
       nat    nat
        |      |
        3      4