逆ポーランド計算機

S式ストリームパーサ版を作ろうと思って書いてたら id:mzp が書いてしまったので方向転換.
逆ポーランド計算機


#load "camlp4o.cma"
type token = Op of string | Num of int
let lexer = Genlex.make_lexer ["+"; "-"; "*"; "/"]

let rec parse = parser
| [<'Int n; e = parse>] -> (Num n) :: e
| [<'Kwd k; e = parse>] -> (Op k) :: e
| [<>] -> []

exception NotOperation
let op (Op s) (Num n1) (Num n2) =
if s = "+" then Num (n1 + n2)
else if s = "-" then Num (n1 - n2)
else if s = "*" then Num (n1 * n2)
else if s = "/" then Num (n1 / n2)
else raise NotOperation

let s = Stack.create ()
let rec calc = function
Num n :: l -> (Stack.push (Num n) s); calc l
| Op o :: l ->
let n1 = Stack.pop s
and n2 = Stack.pop s
in (Stack.push (op (Op o) n2 n1) s); calc l
| [] -> Stack.top s

let inv_polish s =
let n = calc (parse (lexer (Stream.of_string s)))
in
match n with
Num n -> n

Stack モジュールを初めて使ってみた.

実行結果


# inv_polish "3 1 - 10 * 2 /";;

  • : int = 10