HaskellとParsecでLisp REPL その3(Number型の追加)
今回の変更点
REPLで数字を入力するとパースエラーになる。Atom
、List
に続いてNumber
もパースしデータとして扱えるようにしたい。
LispVal
にNumber
型を追加
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
数字が一つ以上続いているのを文字列として捉え、read
でHaskellのIntegerに変換してからNumber
データコンストラクタに渡し、return
でParser
モナド値にしている。
Atom
やList
と違ってロジックが簡単なのでdo
記法はなし。しかし>>=
は処理の流れがけっこう追いにくく感じる。慣れの問題?
評価器・REPL・main
前回と同じく変更なし
実行
REPLを走らせてみるとこんな感じ:
>> a a >> 1 1 >> () () >> (1 2 3) (1 2 3) >> (+ 1 2 3) (+ 1 2 3) >> quit
とりあえず数字を入力してもパースエラーは起きなくなっている。
しかしなんの計算も評価も行われず、ただ単に入力をそのまま出力しているだけ。悲しい。
次回は数値に対する四則演算を評価するように変更する。