오평석
가입: 2014년 10월 17일 올린 글: 8
|
올려짐: 2014년12월21일 0:07 주제: 프로젝트 3번 main + interpreter |
|
|
테스트해보기 편하게 기존의 main에 인터프리터를 넣었습니다.
사용법은 ./main [filename] [input1] [input2] [input3] ... 입니다.
read 해야하는 만큼 인풋이 들어오지 않으면 익셉션이 뜹니다.
만약 인풋이 없는 exp라면 아예 전달하지 않으면 됩니다.
바꾼건 얼마 안되서 특별히 잘못된 건 없어보이는데,
뭔가 잘못된 점이 있으면 알려주세요
코드: |
let filename =
if Array.length Sys.argv < 2
then (prerr_endline "Usage: ./main filename.exp";
exit (-1))
else Sys.argv.(1)
let file_channel = open_in filename
let lexbuf = Lexing.from_channel file_channel
let e = Exp_parser.main Exp_lexer.token lexbuf
let _ = close_in file_channel
let _ = print_endline "========== exp print =========="
let _ = T.pprint_exp e
let _ = print_endline "========== check_exp result =========="
let check_exp_result = T.check_exp e
let _ = print_endline (string_of_bool check_exp_result)
let _ = if check_exp_result then () else exit 0
let _ = print_endline "========== transform result =========="
let c = T.transform e
let _ = T.pprint_cmd c
let _ = print_endline "========== check_cmd result =========="
let check_cmd_result = T.check_cmd c
let _ = print_endline (string_of_bool check_cmd_result)
let _ = if check_cmd_result then () else exit 0
let _ = print_endline "========== transform succeeded =========="
(* use the given interpreter code *)
let rec exp_repeat (iter:int) (e:T.exp) (inputs:int list) : int * (int list) =
if iter = 0
then (0,inputs)
else
let (r1,i1) = exp_eval_rec e inputs in
let (r2,i2) = exp_repeat (iter-1) e i1 in
(r1+r2, i2)
and exp_eval_rec (e:T.exp) (inputs:int list) : int * (int list) =
match e with
| T.Num i -> (i,inputs)
| T.Add (e1,e2) ->
let (r1,i1) = exp_eval_rec e1 inputs in
let (r2,i2) = exp_eval_rec e2 i1 in
(r1+r2,i2)
| T.Minus e1 ->
let (r1,i1) = exp_eval_rec e1 inputs in
(-r1,i1)
| T.Read -> (List.hd inputs,List.tl inputs)
| T.If (e1,e2,e3) ->
let (r1,i1) = exp_eval_rec e1 inputs in
if r1 = 0
then exp_eval_rec e3 i1
else exp_eval_rec e2 i1
| T.Repeat (e1,e2) ->
let (r1,i1) = exp_eval_rec e1 inputs in
exp_repeat r1 e2 i1
let exp_eval (e:T.exp) (inputs:int list) : int = fst (exp_eval_rec e inputs)
let rec cmd_eval_rec
(c:T.cmd list) (idx:int) (inputs:int list) (m:T.var->int) (tg:T.tag->int)
: int =
match List.nth c idx with
| T.HasNum (x,i) ->
let new_m = fun k -> if k = x then i else m k in
cmd_eval_rec c (idx+1) inputs new_m tg
| T.HasVar (x,y) ->
let new_m = fun k -> if k = x then m y else m k in
cmd_eval_rec c (idx+1) inputs new_m tg
| T.HasSum (x,y,z) ->
let new_m = fun k -> if k = x then m y + m z else m k in
cmd_eval_rec c (idx+1) inputs new_m tg
| T.HasSub (x,y,z) ->
let new_m = fun k -> if k = x then m y - m z else m k in
cmd_eval_rec c (idx+1) inputs new_m tg
| T.HasRead x ->
let new_m = fun k -> if k = x then (List.hd inputs) else m k in
cmd_eval_rec c (idx+1) (List.tl inputs) new_m tg
| T.Say x -> m x
| T.Goto (t,x) ->
if m x = 0
then cmd_eval_rec c (idx+1) inputs m tg
else cmd_eval_rec c (tg t) inputs m tg
| T.Tag _ -> failwith "cmd_eval_rec:tag"
| T.Seq _ -> failwith "cmd_eval_rec:seq"
let rec make_cl_rec (c:T.cmd) (tg:T.tag->int) (idx:int)
: T.cmd list * (T.tag->int) * int =
match c with
| T.HasNum _
| T.HasVar _
| T.HasSum _
| T.HasSub _
| T.HasRead _
| T.Say _
| T.Goto _ -> ([c],tg,idx+1)
| T.Tag (t,c') ->
let new_tg = fun k -> if k = t then idx else tg k in
make_cl_rec c' new_tg idx
| T.Seq (c1,c2) ->
let (cl1,tg1,idx1) = make_cl_rec c1 tg idx in
let (cl2,tg2,idx2) = make_cl_rec c2 tg1 idx1 in
(cl1@cl2,tg2,idx2)
exception NoBind
exception NoTagBind
let make_cl (c:T.cmd) : T.cmd list * (T.tag->int) =
let (cl,tg,_) = make_cl_rec c (fun _ -> raise NoTagBind) 0 in
(cl,tg)
let cmd_eval (c:T.cmd) (inputs:int list) : int =
let (cl,tg) = make_cl c in
cmd_eval_rec cl 0 inputs (fun _ -> raise NoBind) tg
let argvs_list = Array.to_list Sys.argv
let inputs_str =
match argvs_list with
| _::_::t -> t
| _ -> exit(-1)
let inputs = List.map (fun x -> int_of_string x) inputs_str
let _ = print_endline "========== run exp =========="
let _ = print_int (exp_eval e inputs)
let _ = print_endline ""
let _ = print_endline "========== run cmd =========="
let _ = print_int (cmd_eval c inputs)
let _ = print_endline ""
|
|
|