132 lines
3.8 KiB
OCaml
132 lines
3.8 KiB
OCaml
type joy_type =
|
|
| JoySymbol of string
|
|
| JoyTrue
|
|
| JoyFalse
|
|
| JoyInt of int
|
|
| JoyList of joy_type list
|
|
|
|
type joy_list = joy_type list
|
|
|
|
let joy_true = JoyTrue
|
|
let joy_false = JoyFalse
|
|
let j_loop = JoySymbol "loop"
|
|
let zero = JoyInt 0
|
|
let dummy = JoyList [ joy_true; joy_false; j_loop; zero ]
|
|
|
|
let rec joy_to_string jt =
|
|
match jt with
|
|
| JoySymbol sym -> sym
|
|
| JoyTrue -> "true"
|
|
| JoyFalse -> "false"
|
|
| JoyInt i -> string_of_int i
|
|
| JoyList el -> "[" ^ expression_to_string el ^ "]"
|
|
|
|
and expression_to_string el = String.concat " " (List.map joy_to_string el)
|
|
|
|
type token = Left_bracket | Right_bracket | Token of string
|
|
|
|
let delimiter str last =
|
|
last >= String.length str || String.contains "[] " (String.get str last)
|
|
|
|
(* string -> int -> int -> token * int *)
|
|
let rec tokenize1 str start last =
|
|
if delimiter str last then (Token (String.sub str start (last - start)), last)
|
|
else tokenize1 str start (last + 1)
|
|
|
|
let rec tokenize0 str start acc =
|
|
if start >= String.length str then acc
|
|
else
|
|
match String.get str start with
|
|
| '[' -> Left_bracket :: tokenize0 str (start + 1) acc
|
|
| ']' -> Right_bracket :: tokenize0 str (start + 1) acc
|
|
| ' ' -> tokenize0 str (start + 1) acc
|
|
| _ ->
|
|
let token, n = tokenize1 str start (start + 1) in
|
|
token :: tokenize0 str n acc
|
|
|
|
let tokenize str = tokenize0 str 0 []
|
|
|
|
(*
|
|
let token_to_string token =
|
|
match token with
|
|
| Left_bracket -> "["
|
|
| Right_bracket -> "]"
|
|
| Token str -> str
|
|
*)
|
|
|
|
exception ParseError of string
|
|
|
|
(*
|
|
let rec parse : token list -> joy_list = fun tokens ->
|
|
match tokens with
|
|
| [] -> []
|
|
| head :: tail ->
|
|
match head with
|
|
| Left_bracket -> let (el, rest) = parse_list tail in el :: parse rest
|
|
| Right_bracket -> raise (ParseError "Extra closing bracket.")
|
|
| Token tok ->
|
|
match tok with
|
|
| "true" -> joy_true :: parse tail
|
|
| "false"-> joy_false :: parse tail
|
|
| _ -> JoySymbol tok :: parse tail
|
|
|
|
*)
|
|
|
|
(* Get the prefix of the list as joy type and return rest of list*)
|
|
let rec expect_right_bracket tokens acc =
|
|
match tokens with
|
|
| [] -> raise (ParseError "Missing closing bracket.")
|
|
| head :: tail -> (
|
|
match head with
|
|
| Right_bracket -> (acc, tail)
|
|
| Left_bracket ->
|
|
(* extract the sub-list *)
|
|
let sub_list, rest = expect_right_bracket tail [] in
|
|
(* continue looking for the expected "]" *)
|
|
let el, rrest = expect_right_bracket rest acc in
|
|
(JoyList sub_list :: el, rrest)
|
|
| Token tok -> (
|
|
let el, rest = expect_right_bracket tail acc in
|
|
match tok with
|
|
| "true" -> (joy_true :: el, rest)
|
|
| "false" -> (joy_false :: el, rest)
|
|
| _ -> (JoySymbol tok :: el, rest)))
|
|
|
|
let foo head tail =
|
|
match head with
|
|
| Left_bracket ->
|
|
let el, rest = expect_right_bracket tail [] in
|
|
(JoyList el, rest)
|
|
| Right_bracket -> raise (ParseError "Extra closing bracket.")
|
|
| Token tok -> (
|
|
match tok with
|
|
| "true" -> (joy_true, tail)
|
|
| "false" -> (joy_false, tail)
|
|
| _ -> (JoySymbol tok, tail))
|
|
|
|
let rec parse0 tokens acc =
|
|
match tokens with
|
|
| [] -> acc
|
|
| head :: tail ->
|
|
let item, rest = foo head tail in
|
|
item :: parse0 rest acc
|
|
|
|
let parse : token list -> joy_list = fun tokens -> parse0 tokens []
|
|
|
|
(*
|
|
|
|
let text_to_expression str =
|
|
let tokens = tokenize str in
|
|
tokens
|
|
|
|
let s = String.concat "" (List.map token_to_string (text_to_expression "1 [2]3" ))
|
|
let s = String.concat " " (List.map token_to_string (tokenize "1 Pat [2]3"))
|
|
*)
|
|
|
|
(* let () = print_endline (joy_to_string dummy) *)
|
|
|
|
let () =
|
|
print_endline (expression_to_string (parse (tokenize "1 2 3[4 5 6[7 8]9 10]11[][][[]]")));
|
|
print_endline (expression_to_string (parse (tokenize "true [ false]true")));
|
|
print_endline (joy_to_string dummy)
|