Arantium Maestum

プログラミング、囲碁、読書の話題

HaskellとParsecでLisp REPL その3(Number型の追加)

今回の変更点

github.com

REPLで数字を入力するとパースエラーになる。AtomListに続いてNumberもパースしデータとして扱えるようにしたい。

LispValNumber型を追加

LispValに新たにNumber型を定義し、Haskellの整数を保持させる:

data LispVal = Atom String
             | List [LispVal]
             | Number Integer

showVal関数は、単にNumberが保持する整数の文字列を返す:

showVal (Number n)      = show n

パーサを拡張

トップレベルのパーサにparseNumberを追加:

parseExpr :: Parser LispVal
parseExpr = parseAtom
        <|> parseList
        <|> parseNumber

parseNumberの定義:

parseNumber :: Parser LispVal
parseNumber = many1 digit >>= return . Number . read

数字が一つ以上続いているのを文字列として捉え、readHaskellのIntegerに変換してからNumberデータコンストラクタに渡し、returnParserモナド値にしている。

AtomListと違ってロジックが簡単なのでdo記法はなし。しかし>>=は処理の流れがけっこう追いにくく感じる。慣れの問題?

評価器・REPL・main

前回と同じく変更なし

実行

REPLを走らせてみるとこんな感じ:

>> a
a
>> 1
1
>> ()
()
>> (1 2 3)
(1 2 3)
>> (+ 1 2 3)
(+ 1 2 3)
>> quit

とりあえず数字を入力してもパースエラーは起きなくなっている。

しかしなんの計算も評価も行われず、ただ単に入力をそのまま出力しているだけ。悲しい。

次回は数値に対する四則演算を評価するように変更する。