■
http://d.hatena.ne.jp/komamitsu/20091012/1255307045
以前、ocamlyacc辺りを弄っていて萌えてこなくて挫折、というケースがあったのだけど、構文解析が云々という以前にまともに構文設計らしきことをしていないのが、そもそもの原因ではないかと。
その辺を少し練習してみることに。
最初は四則演算に変数を加えた簡単なものをやってみる。
open Printf type symbol = string type stmt = | Expr of expr | Bind of symbol * expr | Print of expr and expr = | Add of expr * expr | Sub of expr * expr | Mul of expr * expr | Div of expr * expr | Atom of atom | Appl of symbol and atom = Int of int let rec eval_expr env = function | Add (a, b) -> (eval_expr env a) + (eval_expr env b) | Sub (a, b) -> (eval_expr env a) - (eval_expr env b) | Mul (a, b) -> (eval_expr env a) * (eval_expr env b) | Div (a, b) -> (eval_expr env a) / (eval_expr env b) | Atom a -> (match a with Int a -> a) | Appl k -> Hashtbl.find env k let rec eval_stmt env stmt = ignore ( match stmt with | Expr e -> ignore (eval_expr env e) | Bind (s, e) -> Hashtbl.replace env s (eval_expr env e) | Print e -> printf "=> %d\n" (eval_expr env e) ); env let sample_stmt_list = (* * x = 17 - 13; * y = 3 + 7; * 31 + 11; * print (5 * x / y); *) [ Bind ("x", Sub (Atom (Int 17), Atom (Int 13))); Bind ("y", Add (Atom (Int 3), Atom (Int 7))); Expr (Add (Atom (Int 31), Atom (Int 11))); Print (Div (Mul (Atom (Int 5), Appl "x"), Appl "y")) ] let _ = let empty = Hashtbl.create 10 in List.fold_left (fun env stmt -> eval_stmt env stmt) empty sample_stmt_list (* stdout : "=> 2" *)
これだけでも結構悩めてとても楽しい。とりあえずprintが文になっているのが寂しいけれど。
あと、世の中のプログラミング言語の構文仕様が気になってきたのは、なかなか良い兆候だと思う。