I'm trying to make the function which takes string and transforms it to boolean expression. For example:for input ((x10+~1)*x132)
it should give times(plus(var 10,compl 1),var 132)
, but it gives times(plus(var #,compl #),var 132)
. Where do hashtags come from??
datatype boolexp = zero
| one
| plus of boolexp * boolexp
| times of boolexp * boolexp
| var of int
| compl of boolexp
exception InvalidInput
(* takes the first n elements *)
fun take (_, 0) = nil
| take (nil, _) = raise InvalidInput
| take (h::t, n) = if n < 0
then raise InvalidInput
else h::take(t, n-1)
(* drops the frist n elements *)
fun drop (xs, 0) = xs
| drop (nil, _) = raise InvalidInput
| drop (h::t,n) = if n < 0
then raise InvalidInput
else drop (t, n-1)
(* converts string to integer *)
fun charlist_to_int (nil) = raise InvalidInput
| charlist_to_int (xs) =
let fun helper_int_rev (nil) = 0
| helper_int_rev (h::t) = if h >= #"0" andalso h <= #"9"
then helper_int_rev t * 10 + (ord h - ord #"0")
else raise InvalidInput
in helper_int_rev (rev xs) end;
(* finds the operator and its position *)
fun searchfor_oper (nil,_,_) = raise InvalidInput
| searchfor_oper (#"("::t, np, pos) = searchfor_oper (t, np+1, pos+1)
| searchfor_oper (#")"::t, np, pos) = searchfor_oper(t, np-1, pos+1)
| searchfor_oper (#"+"::t, 0, pos) = (pos, #"+")
| searchfor_oper (#"*"::t, 0, pos) = (pos, #"*")
| searchfor_oper (h::t, np, pos) = searchfor_oper (t, np, pos+1)
fun beparse_helper (nil) = raise InvalidInput
| beparse_helper (h::t) =
if h = #"x" then if hd(t)= #"0" then raise InvalidInput
else var (charlist_to_int (t))
else if h = #"0" then if t = nil then zero else raise InvalidInput
else if h = #"1" then if t = nil then one else raise InvalidInput
else if h = #"~" then compl(beparse_helper(t))
else if h = #"(" then
let
val lst = if hd (rev t)= #")" then take(t, length(t)-1) else raise InvalidInput
val (pos, oper) = searchfor_oper (lst, 0, 1)
in
if oper = (#"+")
then plus(beparse_helper(take(lst,pos-1)), beparse_helper(drop(lst,pos)))
else if oper = (#"*")
then times(beparse_helper(take(lst,pos-1)),beparse_helper(drop(lst,pos)))
else raise InvalidInput
end
else raise InvalidInput;
fun beparse(s) = beparse_helper(explode(s));
(*TESTING*)
beparse ("((x10+~1)*x132)");
I don't think that it is SML
per se so much as SML/NJ
default REPL output. In the grand scheme of things the REPL is for development/debugging -- not the environment for the finished program to run it. Recursive data structures such as trees can give quickly give rise to values which are too big to conveniently print. The REPL truncates the output in a couple of ways. For lists it will print around a dozen elements and then use ...
. For things like trees it will print down a few levels and then use a #
to indicate that you have reached the level where the truncation happens. If you find this inconvenient you can do one of two things:
1) The logical printing depth in SML/NJ can be altered by evaluating Control.Print.printDepth := 20;
(or however much you want) in the REPL
2) Perhaps a little more principled but more work -- write a custom pretty-printer (say pprint
) for your values and evaluate e.g. pprint v;
in the REPL rather than just v;