From 59d10e1bd703f65e12fef85bceef4204f82685fb Mon Sep 17 00:00:00 2001 From: Chouser Date: Thu, 22 Jan 2015 02:59:48 -0500 Subject: Ocaml: Added step 1, missing some optional functionality --- ocaml/reader.ml | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 ocaml/reader.ml (limited to 'ocaml/reader.ml') 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 + -- cgit v1.2.3 From 921a951fe4d088e60ce25866344bd534420f9ec6 Mon Sep 17 00:00:00 2001 From: Chouser Date: Thu, 22 Jan 2015 02:59:48 -0500 Subject: Ocaml: Add step 2, nothing optional --- ocaml/reader.ml | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 51ab522..c32fa91 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -3,7 +3,7 @@ let find_re re str = (List.filter (function | Str.Delim x -> true | Str.Text x -> false) (Str.full_split re str)) ;; -let token_re = (Str.regexp "~@\\|[][{}()'`~^@]\\|\"\\(\\\\.\\|[^\"]\\)*\"\\|;.*\\|[^][ \n{}('\"`,;)]*") +let token_re = (Str.regexp "~@\\|[][{}()'`~^@]\\|\"\\(\\\\.\\|[^\"]\\)*\"\\|;.*\\|[^][ \n{}('\"`,;)]*") type reader = { form : Types.mal_type; @@ -36,11 +36,11 @@ let rec read_list list_reader = raise End_of_file; | token :: tokens -> if Str.string_match (Str.regexp "[])}]") token 0 then - {list_form = list_reader.list_form; tokens = tokens} + {list_form = list_reader.list_form; tokens = tokens} else - let reader = read_form list_reader.tokens in + let reader = read_form list_reader.tokens in read_list {list_form = list_reader.list_form @ [reader.form]; - tokens = reader.tokens} + tokens = reader.tokens} and read_quote sym tokens = let reader = read_form tokens in {form = Types.MalList [ Types.Symbol sym; reader.form ]; @@ -50,17 +50,15 @@ and read_form all_tokens = | [] -> raise End_of_file; | token :: tokens -> match token with - | "'" -> read_quote "quote" tokens - | "`" -> read_quote "quasiquote" tokens - | "~" -> read_quote "unquote" tokens + | "'" -> 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 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 -- cgit v1.2.3 From f2f11f6279e1b242ba75136cd037fabdd176118a Mon Sep 17 00:00:00 2001 From: Chouser Date: Fri, 23 Jan 2015 22:54:15 -0500 Subject: Ocaml: rename Types.MalList to Types.List --- ocaml/reader.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index c32fa91..58e72fe 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -43,7 +43,7 @@ let rec read_list list_reader = tokens = reader.tokens} and read_quote sym tokens = let reader = read_form tokens in - {form = Types.MalList [ Types.Symbol sym; reader.form ]; + {form = Types.List [ Types.Symbol sym; reader.form ]; tokens = reader.tokens} and read_form all_tokens = match all_tokens with @@ -56,7 +56,7 @@ and read_form all_tokens = | "~@" -> read_quote "splice-unquote" tokens | "[" | "(" | "{" -> let list_reader = read_list {list_form = []; tokens = tokens} in - {form = Types.MalList list_reader.list_form; + {form = Types.List list_reader.list_form; tokens = list_reader.tokens} | _ -> {form = read_atom token; tokens = tokens} -- cgit v1.2.3 From b7ffcab96166f15d6203551ffbc487da5076f92e Mon Sep 17 00:00:00 2001 From: Chouser Date: Sat, 24 Jan 2015 00:44:51 -0500 Subject: Ocaml: Add read, print for vector, map --- ocaml/reader.ml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 58e72fe..c452e05 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -54,10 +54,18 @@ and read_form all_tokens = | "`" -> read_quote "quasiquote" tokens | "~" -> read_quote "unquote" tokens | "~@" -> read_quote "splice-unquote" tokens - | "[" | "(" | "{" -> let list_reader = + | "(" -> let list_reader = read_list {list_form = []; tokens = tokens} in {form = Types.List list_reader.list_form; tokens = list_reader.tokens} + | "{" -> let list_reader = + read_list {list_form = []; tokens = tokens} in + {form = Types.Map list_reader.list_form; + tokens = list_reader.tokens} + | "[" -> let list_reader = + read_list {list_form = []; tokens = tokens} in + {form = Types.Vector 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 -- cgit v1.2.3 From a878f3bb778513c0cc8bbeb1a8ff61664e43de29 Mon Sep 17 00:00:00 2001 From: Chouser Date: Sun, 25 Jan 2015 23:30:37 -0500 Subject: Ocaml: Use a real map type T.Map is now a real OCaml binary-tree map, and supports arbitrary mal value types for both keys and values. Metadata support is provided in the data objects, but not yet in the printer, reader, or core library. --- ocaml/reader.ml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index c452e05..6827597 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -1,3 +1,6 @@ +module T = Types.Types + (* ^file ^module *) + 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) @@ -17,17 +20,17 @@ type list_reader = { let read_atom token = match token with - | "nil" -> Types.Nil - | "true" -> Types.Bool true - | "false" -> Types.Bool false + | "nil" -> T.Nil + | "true" -> T.Bool true + | "false" -> T.Bool false | _ -> match token.[0] with - | '0'..'9' -> Types.Int (int_of_string token) - | '"' -> Types.String (Str.global_replace (Str.regexp "\\\\\\(.\\)") + | '0'..'9' -> T.Int (int_of_string token) + | '"' -> T.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 + | ':' -> T.Keyword (Str.replace_first (Str.regexp "^:") "" token) + | _ -> Types.symbol token let rec read_list list_reader = match list_reader.tokens with @@ -43,7 +46,7 @@ let rec read_list list_reader = tokens = reader.tokens} and read_quote sym tokens = let reader = read_form tokens in - {form = Types.List [ Types.Symbol sym; reader.form ]; + {form = Types.list [ Types.symbol sym; reader.form ]; tokens = reader.tokens} and read_form all_tokens = match all_tokens with @@ -54,17 +57,18 @@ and read_form all_tokens = | "`" -> read_quote "quasiquote" tokens | "~" -> read_quote "unquote" tokens | "~@" -> read_quote "splice-unquote" tokens + | "@" -> read_quote "deref" tokens | "(" -> let list_reader = read_list {list_form = []; tokens = tokens} in - {form = Types.List list_reader.list_form; + {form = Types.list list_reader.list_form; tokens = list_reader.tokens} | "{" -> let list_reader = read_list {list_form = []; tokens = tokens} in - {form = Types.Map list_reader.list_form; + {form = Types.list_into_map Types.MalMap.empty list_reader.list_form; tokens = list_reader.tokens} | "[" -> let list_reader = read_list {list_form = []; tokens = tokens} in - {form = Types.Vector list_reader.list_form; + {form = Types.vector list_reader.list_form; tokens = list_reader.tokens} | _ -> {form = read_atom token; tokens = tokens} -- cgit v1.2.3 From e64878d0af10d7e391e2070ddd02756042bec7b9 Mon Sep 17 00:00:00 2001 From: Chouser Date: Mon, 26 Jan 2015 19:16:23 -0500 Subject: Ocaml: add meta, with-meta, and ^ reader support --- ocaml/reader.ml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 6827597..a6c2366 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -32,6 +32,14 @@ let read_atom token = | ':' -> T.Keyword (Str.replace_first (Str.regexp "^:") "" token) | _ -> Types.symbol token +let with_meta obj meta = + match obj with + | T.List { T.value = value } -> T.List { T.value = value; T.meta = meta }; + | T.Map { T.value = value } -> T.Map { T.value = value; T.meta = meta }; + | T.Vector { T.value = value } -> T.Vector { T.value = value; T.meta = meta }; + | T.Symbol { T.value = value } -> T.Symbol { T.value = value; T.meta = meta }; + | _ -> raise (Invalid_argument "metadata not supported on this type") + let rec read_list list_reader = match list_reader.tokens with | [] -> output_string stderr "expected ')', got EOF\n"; @@ -58,16 +66,20 @@ and read_form all_tokens = | "~" -> read_quote "unquote" tokens | "~@" -> read_quote "splice-unquote" tokens | "@" -> read_quote "deref" tokens - | "(" -> let list_reader = - read_list {list_form = []; tokens = tokens} in + | "^" -> + let meta = read_form tokens in + let value = read_form meta.tokens in + {form = with_meta value.form meta.form; tokens = value.tokens} + | "(" -> + let list_reader = read_list {list_form = []; tokens = tokens} in {form = Types.list list_reader.list_form; tokens = list_reader.tokens} - | "{" -> let list_reader = - read_list {list_form = []; tokens = tokens} in + | "{" -> + let list_reader = read_list {list_form = []; tokens = tokens} in {form = Types.list_into_map Types.MalMap.empty list_reader.list_form; tokens = list_reader.tokens} - | "[" -> let list_reader = - read_list {list_form = []; tokens = tokens} in + | "[" -> + let list_reader = read_list {list_form = []; tokens = tokens} in {form = Types.vector list_reader.list_form; tokens = list_reader.tokens} | _ -> {form = read_atom token; tokens = tokens} -- cgit v1.2.3 From 04e33074cc516fe4b79a6319c7a211002902a846 Mon Sep 17 00:00:00 2001 From: Chouser Date: Mon, 26 Jan 2015 23:05:13 -0500 Subject: Ocaml: All optional tests passing up thru step 4 --- ocaml/reader.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index a6c2366..9754444 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -69,7 +69,9 @@ and read_form all_tokens = | "^" -> let meta = read_form tokens in let value = read_form meta.tokens in - {form = with_meta value.form meta.form; tokens = value.tokens} + {(*form = with_meta value.form meta.form;*) + form = Types.list [Types.symbol "with-meta"; value.form; meta.form]; + tokens = value.tokens} | "(" -> let list_reader = read_list {list_form = []; tokens = tokens} in {form = Types.list list_reader.list_form; -- cgit v1.2.3 From 16b177329cac77136b236dfb3645e4be4e3df297 Mon Sep 17 00:00:00 2001 From: Chouser Date: Wed, 28 Jan 2015 08:27:32 -0500 Subject: Ocaml: fix string escaping and printing --- ocaml/reader.ml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 9754444..96404aa 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -6,6 +6,11 @@ let find_re re str = (List.filter (function | Str.Delim x -> true | Str.Text x -> false) (Str.full_split re str)) ;; +let gsub re f str = + String.concat + "" (List.map (function | Str.Delim x -> f x | Str.Text x -> x) + (Str.full_split re str)) + let token_re = (Str.regexp "~@\\|[][{}()'`~^@]\\|\"\\(\\\\.\\|[^\"]\\)*\"\\|;.*\\|[^][ \n{}('\"`,;)]*") type reader = { @@ -26,9 +31,11 @@ let read_atom token = | _ -> match token.[0] with | '0'..'9' -> T.Int (int_of_string token) - | '"' -> T.String (Str.global_replace (Str.regexp "\\\\\\(.\\)") - "\\1" - (String.sub token 1 ((String.length token) - 2))) + | '"' -> T.String (gsub (Str.regexp "\\\\.") + (function + | "\\n" -> "\n" + | x -> String.sub x 1 1) + (String.sub token 1 ((String.length token) - 2))) | ':' -> T.Keyword (Str.replace_first (Str.regexp "^:") "" token) | _ -> Types.symbol token -- cgit v1.2.3 From 387da0bba9e58e35c6ab24a131b445d4330a8520 Mon Sep 17 00:00:00 2001 From: Chouser Date: Wed, 28 Jan 2015 09:06:53 -0500 Subject: Ocaml: fix list and comment parsing --- ocaml/reader.ml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 96404aa..0bb4328 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -47,18 +47,21 @@ let with_meta obj meta = | T.Symbol { T.value = value } -> T.Symbol { T.value = value; T.meta = meta }; | _ -> raise (Invalid_argument "metadata not supported on this type") -let rec read_list list_reader = +let rec read_list eol list_reader = match list_reader.tokens with - | [] -> output_string stderr "expected ')', got EOF\n"; + | [] -> output_string stderr ("expected '" ^ eol ^ "', got EOF\n"); flush stderr; raise End_of_file; | token :: tokens -> - if Str.string_match (Str.regexp "[])}]") token 0 then + if Str.string_match (Str.regexp eol) token 0 then {list_form = list_reader.list_form; tokens = tokens} + else if token.[0] = ';' then + read_list eol { 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} + read_list eol {list_form = list_reader.list_form @ [reader.form]; + tokens = reader.tokens} and read_quote sym tokens = let reader = read_form tokens in {form = Types.list [ Types.symbol sym; reader.form ]; @@ -80,18 +83,20 @@ and read_form all_tokens = form = Types.list [Types.symbol "with-meta"; value.form; meta.form]; tokens = value.tokens} | "(" -> - let list_reader = read_list {list_form = []; tokens = tokens} in + let list_reader = read_list ")" {list_form = []; tokens = tokens} in {form = Types.list list_reader.list_form; tokens = list_reader.tokens} | "{" -> - let list_reader = read_list {list_form = []; tokens = tokens} in + let list_reader = read_list "}" {list_form = []; tokens = tokens} in {form = Types.list_into_map Types.MalMap.empty list_reader.list_form; tokens = list_reader.tokens} | "[" -> - let list_reader = read_list {list_form = []; tokens = tokens} in + let list_reader = read_list "]" {list_form = []; tokens = tokens} in {form = Types.vector list_reader.list_form; tokens = list_reader.tokens} - | _ -> {form = read_atom token; tokens = tokens} + | _ -> if token.[0] = ';' + then read_form tokens + else {form = read_atom token; tokens = tokens} let read_str str = (read_form (List.filter ((<>) "") (find_re token_re str))).form -- cgit v1.2.3 From 776cf577064c2676e33987546f10c2be80b26344 Mon Sep 17 00:00:00 2001 From: Chouser Date: Wed, 28 Jan 2015 13:13:44 -0500 Subject: Ocaml: Finish adding step 6 --- ocaml/reader.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 0bb4328..36f0b2a 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -1,10 +1,17 @@ module T = Types.Types (* ^file ^module *) +let slurp filename = + let chan = open_in filename in + let b = Buffer.create 27 in + Buffer.add_channel b chan (in_channel_length chan) ; + close_in chan ; + Buffer.contents b + 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)) ;; + (Str.full_split re str)) let gsub re f str = String.concat -- cgit v1.2.3 From ecd3b6d8e551dd87934142b0323d9b75134bbea9 Mon Sep 17 00:00:00 2001 From: Chouser Date: Thu, 29 Jan 2015 23:29:54 -0500 Subject: OCaml: Add step 9 --- ocaml/reader.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index 36f0b2a..cf8c141 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -48,10 +48,11 @@ let read_atom token = let with_meta obj meta = match obj with - | T.List { T.value = value } -> T.List { T.value = value; T.meta = meta }; - | T.Map { T.value = value } -> T.Map { T.value = value; T.meta = meta }; - | T.Vector { T.value = value } -> T.Vector { T.value = value; T.meta = meta }; - | T.Symbol { T.value = value } -> T.Symbol { T.value = value; T.meta = meta }; + | T.List { T.value = v } -> T.List { T.value = v; T.meta = meta; T.is_macro = false }; + | T.Map { T.value = v } -> T.Map { T.value = v; T.meta = meta; T.is_macro = false }; + | T.Vector { T.value = v } -> T.Vector { T.value = v; T.meta = meta; T.is_macro = false }; + | T.Symbol { T.value = v } -> T.Symbol { T.value = v; T.meta = meta; T.is_macro = false }; + | T.Fn { T.value = v } -> T.Fn { T.value = v; T.meta = meta; T.is_macro = false }; | _ -> raise (Invalid_argument "metadata not supported on this type") let rec read_list eol list_reader = -- cgit v1.2.3 From 2b8e0ea42046505635e8f4c9d96e594c595948c2 Mon Sep 17 00:00:00 2001 From: Chouser Date: Fri, 30 Jan 2015 09:10:24 -0500 Subject: OCaml: put macro flag in metadata rather than special type field --- ocaml/reader.ml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'ocaml/reader.ml') diff --git a/ocaml/reader.ml b/ocaml/reader.ml index cf8c141..7456cf8 100644 --- a/ocaml/reader.ml +++ b/ocaml/reader.ml @@ -48,11 +48,12 @@ let read_atom token = let with_meta obj meta = match obj with - | T.List { T.value = v } -> T.List { T.value = v; T.meta = meta; T.is_macro = false }; - | T.Map { T.value = v } -> T.Map { T.value = v; T.meta = meta; T.is_macro = false }; - | T.Vector { T.value = v } -> T.Vector { T.value = v; T.meta = meta; T.is_macro = false }; - | T.Symbol { T.value = v } -> T.Symbol { T.value = v; T.meta = meta; T.is_macro = false }; - | T.Fn { T.value = v } -> T.Fn { T.value = v; T.meta = meta; T.is_macro = false }; + | T.List { T.value = v } + -> T.List { T.value = v; T.meta = meta }; | T.Map { T.value = v } + -> T.Map { T.value = v; T.meta = meta }; | T.Vector { T.value = v } + -> T.Vector { T.value = v; T.meta = meta }; | T.Symbol { T.value = v } + -> T.Symbol { T.value = v; T.meta = meta }; | T.Fn { T.value = v } + -> T.Fn { T.value = v; T.meta = meta }; | _ -> raise (Invalid_argument "metadata not supported on this type") let rec read_list eol list_reader = -- cgit v1.2.3