Top > TigerBook > PROGRAM1
Counter: 2681, today: 1, yesterday: 0

Chapter 1 の PROGRAM

導入部なので概要説明と思ったらいきなりプログラムを書かせるあたり なかなか鬼。SML に慣れておけ、と言う意味もあるのだろう。

教科書では以下の型定義と

type id = string
datatype binop = Plus | Minus | Times | Div
datatype stm =
        CompoundStm of stm * stm
      | AssignStm   of id * exp
      | PrintStm of exp list
    and exp =
        IdExp of id
      | NumExp of int
      | OpExp of exp * binop * exp
      | EseqExp of stm * exp

以下の構文木が与えられている。

val prog =
   CompoundStm( AssignStm( "a", OpExp(NumExp 5, Plus, NumExp 3)),
		 CompoundStm(
		   AssignStm(
		     "b",
		     EseqExp( PrintStm [IdExp "a",
					OpExp( IdExp "a", Minus, NumExp 1)],
			      OpExp( NumExp 10, Times, IdExp "a" ))),
		   PrintStm[IdExp "b"]))

PROGRAM 1

構文木に含まれる print の引数の最大値を求める。

fun maxargs stm =
   let
	fun max a b = if a > b then a else b
	fun max_stm_rec m stm =
	    case stm of
		CompoundStm (u,v) => max (max_stm_rec m u) (max_stm_rec m v)
	      | AssignStm (i,e) => max_exp_rec m e
	      | PrintStm el => max_expl_rec m 0 el
	and max_exp_rec m exp =
	    case exp of
		IdExp i => m
	      |	NumExp n => m
	      | OpExp (e1,b,e2) => max (max_exp_rec m e1) (max_exp_rec m e2)
	      | EseqExp (s,e) => max (max_stm_rec m s) (max_exp_rec m e)
	and max_expl_rec m p elist =
	    case elist of
		[] => max m p
	      |	hd::tl => max_expl_rec (max_exp_rec m hd) (p+1) tl
   in
	max_stm_rec 0 stm
   end

PROGRAM 2

与えられた構文木を翻訳実行する。 書いてから思ったけど print ERROR してるところは exception 〜 raise のほうがいいね。 (文法を調べずに書いたんで。あは。)

fun interp stm =
   let
	fun searchenv env key =
	    case env of
		(i,v)::tl => if i = key then v else searchenv tl key
	      | [] =>(print "ERROR\n";0)
	fun stm_rec env stm =
	    case stm of
		CompoundStm (u,v) => stm_rec (stm_rec env u) v
	      | AssignStm (i,e) => let val (env_new, evald) = exp_rec env e in
				       (i, evald) :: env_new
				   end
	      | PrintStm el => let val env_new = pr_expl_rec env el in
				   print "\n"; env_new
			       end
	and exp_rec env exp =
	    case exp of
		IdExp i => (env, (searchenv env i))
	      |	NumExp n => (env, n)
	      | EseqExp (s,e) => exp_rec (stm_rec env s) e
	      | OpExp (e1,b,e2) =>
		let val (env_new1, e1d) = exp_rec env e1 
		    val (env_new2, e2d) = exp_rec env_new1 e2 in
		    case b of
			Plus  => (env_new2, e1d + e2d)
		      | Minus => (env_new2, e1d - e2d)
		      | Times => (env_new2, e1d * e2d)
		      | Div   => (env_new2, e1d div e2d)
		end
	and pr_expl_rec env elist =
	    case elist of
	    	hd::tl => let val (env_new, evald) = exp_rec env hd in
			      print ((Int.toString evald)^" ");
			      pr_expl_rec env_new tl
			  end
	      | [] => env
   in
	stm_rec [] stm
   end

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup Referer   Help   RSS of recent changes
Last-modified: (4850d)