aboutsummaryrefslogtreecommitdiff
path: root/ocaml/reader.ml
diff options
context:
space:
mode:
authorChouser <chouser@n01se.net>2015-01-22 02:59:48 -0500
committerChouser <chouser@n01se.net>2015-01-30 12:54:42 -0500
commit59d10e1bd703f65e12fef85bceef4204f82685fb (patch)
treed603eb4b18dca19d4351b40164765363f9866d3c /ocaml/reader.ml
parentca51c4f77235d8f9b8606ebc8c255778c83c9050 (diff)
downloadmal-59d10e1bd703f65e12fef85bceef4204f82685fb.tar.gz
mal-59d10e1bd703f65e12fef85bceef4204f82685fb.zip
Ocaml: Added step 1, missing some optional functionality
Diffstat (limited to 'ocaml/reader.ml')
-rw-r--r--ocaml/reader.ml66
1 files changed, 66 insertions, 0 deletions
diff --git a/ocaml/reader.ml b/ocaml/reader.ml
new file mode 100644
index 0000000..51ab522
--- /dev/null
+++ b/ocaml/reader.ml
@@ -0,0 +1,66 @@
+let find_re re str =
+ List.map (function | Str.Delim x -> x | Str.Text x -> "impossible!")
+ (List.filter (function | Str.Delim x -> true | Str.Text x -> false)
+ (Str.full_split re str)) ;;
+
+let token_re = (Str.regexp "~@\\|[][{}()'`~^@]\\|\"\\(\\\\.\\|[^\"]\\)*\"\\|;.*\\|[^][ \n{}('\"`,;)]*")
+
+type reader = {
+ form : Types.mal_type;
+ tokens : string list;
+}
+
+type list_reader = {
+ list_form : Types.mal_type list;
+ tokens : string list;
+}
+
+let read_atom token =
+ match token with
+ | "nil" -> Types.Nil
+ | "true" -> Types.Bool true
+ | "false" -> Types.Bool false
+ | _ ->
+ match token.[0] with
+ | '0'..'9' -> Types.Int (int_of_string token)
+ | '"' -> Types.String (Str.global_replace (Str.regexp "\\\\\\(.\\)")
+ "\\1"
+ (String.sub token 1 ((String.length token) - 2)))
+ | ':' -> Types.Keyword (Str.replace_first (Str.regexp "^:") "" token)
+ | _ -> Types.Symbol token
+
+let rec read_list list_reader =
+ match list_reader.tokens with
+ | [] -> output_string stderr "expected ')', got EOF\n";
+ flush stderr;
+ raise End_of_file;
+ | token :: tokens ->
+ if Str.string_match (Str.regexp "[])}]") token 0 then
+ {list_form = list_reader.list_form; tokens = tokens}
+ else
+ let reader = read_form list_reader.tokens in
+ read_list {list_form = list_reader.list_form @ [reader.form];
+ tokens = reader.tokens}
+and read_quote sym tokens =
+ let reader = read_form tokens in
+ {form = Types.MalList [ Types.Symbol sym; reader.form ];
+ tokens = reader.tokens}
+and read_form all_tokens =
+ match all_tokens with
+ | [] -> raise End_of_file;
+ | token :: tokens ->
+ match token with
+ | "'" -> read_quote "quote" tokens
+ | "`" -> read_quote "quasiquote" tokens
+ | "~" -> read_quote "unquote" tokens
+ | "~@" -> read_quote "splice-unquote" tokens
+ | _ ->
+ match token.[0] with
+ | '[' | '(' | '{' -> let list_reader =
+ read_list {list_form = []; tokens = tokens} in
+ {form = Types.MalList list_reader.list_form;
+ tokens = list_reader.tokens}
+ | _ -> {form = read_atom token; tokens = tokens}
+
+let read_str str = (read_form (List.filter ((<>) "") (find_re token_re str))).form
+