@ -1,11 +1,19 @@
include Token
let rec split_at1 l n =
if n = 0 then ( [] , l ) else
match l with
| [] -> ( [] , [] )
| h :: t -> let ( l1 , l2 ) = split_at1 t ( n - 1 ) in ( h :: l1 , l2 ) ;;
let safe_hd xs =
match xs with
| [] -> None
| x :: _ -> Some x
let safe_tl xs =
match xs with
| [] -> None
| _ :: xs -> Some xs
let safe_list xs =
match List . length xs with
@ -24,7 +32,6 @@ let if_list_peek xs n v =
module Parser = struct
include Token
open Base
let split_with ( l : Token . token_type list ) left right =
let f ( length , level ) ( i , tk ) =
@ -36,9 +43,11 @@ module Parser = struct
| a when Token . equal a right -> ( length , level - 1 )
| _ -> ( length , level )
in
match List . fold_left ~ f : f ~ init : ( List . length l , 1 ) ( List . mapi ~ f : ( fun i e -> ( i , e ) ) l ) with
match List . fold_left f ( List . length l , 1 ) ( List . mapi ( fun i e -> ( i , e ) ) l ) with
| ( i , _ ) -> Some ( split_at1 l i )
module Obj = Map . Make ( String ) ;;
type hvalue =
| INTEGER of int
| FLOAT of float
@ -46,7 +55,7 @@ module Parser = struct
| BINARY of Bytes . t
| NULL
| ARRAY of hvalue List . t
| OBJECT of ( string , hvalue , String . comparator_witness ) Map . t
| OBJECT of hvalue Obj . t
let rec equal a b =
match ( a , b ) with
@ -56,7 +65,7 @@ module Parser = struct
| ( BINARY a , BINARY b ) -> Bytes . equal a b
| ( NULL , NULL ) -> true
| ( ARRAY a , ARRAY b ) -> List . equal equal a b
| ( OBJECT a , OBJECT b ) -> Map . equal equal a b
| ( OBJECT a , OBJECT b ) -> Obj . equal equal a b
| _ -> false
@ -64,13 +73,11 @@ module Parser = struct
| INTEGER a -> " INTEGER: " ^ Int . to_string a
| FLOAT a -> " INTEGER: " ^ Float . to_string a
| STRING a -> " INTEGER: " ^ a
| BINARY a -> " BINARY " ^ Bytes . fold a ~ init : " " ~ f : ( fun acc b -> acc ^ Printf . sprintf " \\ x%2x " ( Char . to_int b ) )
| BINARY a -> " BINARY " ^ Bytes . fold _left ( fun acc b -> acc ^ Printf . sprintf " \\ x%2x " ( Char . code b ) ) " " a
| NULL -> " NULL "
| ARRAY a -> " ARRAY [ " ^ ( String . concat ~ sep : " , " ( List . map a ~ f : hvalue_to_string) ) ^ " ] "
| OBJECT a -> " OBJECT { " ^ ( String . concat ~ sep : " , " ( List . map ( Map . to_alist a ) ~ f : ( fun ( k , v ) -> k ^ " : ( " ^ ( hvalue_to_string v ) ^ " ) " ) ) ) ^ " } "
| ARRAY a -> " ARRAY [ " ^ ( String . concat " , " ( List . map hvalue_to_string a ) ) ^ " ] "
| OBJECT a -> " OBJECT { " ^ ( String . concat " , " ( List . map ( fun ( k , v ) -> k ^ " : ( " ^ ( hvalue_to_string v ) ^ " ) " ) ( Obj . to_list a ) ) ) ^ " } "
let pretty_print ppf tok = Fmt . pf ppf " HValue %s " ( hvalue_to_string tok )
let parse_primitive token =
match token with
| Token . INTEGER a -> INTEGER a
@ -81,17 +88,17 @@ module Parser = struct
| _ -> failwith " Not a primitive token "
let print_token_array tokens =
List . map tokens ~ f : Token . token_to_string | > String . concat ~ sep : " ; "
List . map Token . token_to_string tokens | > String . concat " ; "
let rec parse tokens =
match List . hd tokens with
match safe_ hd tokens with
| Some ( Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t ) -> parse_primitive t
| Some ( Token . LBRACE ) -> ( match List . tl tokens with
| Some ( Token . LBRACE ) -> ( match safe_ tl tokens with
| Some ( tl ) -> parse_object tl
| _ -> failwith " Not a valid hcfg file " )
| Some ( Token . LBRACKET ) -> ( match List . tl tokens with
| Some ( Token . LBRACKET ) -> ( match safe_ tl tokens with
| Some ( tl ) -> parse_arr tl
| _ -> failwith " Not a valid hcfg file " )
| Some ( Token . EOF ) -> failwith " Empty tree "
@ -100,33 +107,38 @@ module Parser = struct
let rec parse_object_i tkns acc =
match safe_list tkns with
| ( Some hd , Some tl ) -> ( match hd with
| Token . IDENT i when if_list_peek tl 0 Token . COLON -> ( match List . nth tl 1 with
| Some ( Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t ) when if_list_peek tl 2 Token . COMMA -> let ( _ arr , rest ) = split_at1 tl 3 in parse_object_i rest ( Map. set acc ~ key : i ~ data : ( parse_primitive t ) )
| Some ( Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t ) when if_list_peek tl 2 Token . RBRACE -> let ( _ arr , rest ) = split_at1 tl 2 in parse_object_i rest ( Map. set acc ~ key : i ~ data : ( parse_primitive t ) )
| Token . IDENT i when if_list_peek tl 0 Token . COLON -> ( match List . nth _opt tl 1 with
| Some ( Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t ) when if_list_peek tl 2 Token . COMMA -> let ( _ arr , rest ) = split_at1 tl 3 in parse_object_i rest ( Obj. add i ( parse_primitive t ) acc )
| Some ( Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t ) when if_list_peek tl 2 Token . RBRACE -> let ( _ arr , rest ) = split_at1 tl 2 in parse_object_i rest ( Obj. add i ( parse_primitive t ) acc )
| Some Token . LBRACKET -> ( match split_with ( list_skip tl 2 ) Token . LBRACKET Token . RBRACKET with
| Some ( arr , rest ) ->
parse_object_i ( rest ) ( Map. set acc ~ key : i ~ data : ( parse_arr arr ) )
parse_object_i ( rest ) ( Obj. add i ( parse_arr arr ) acc )
| None -> failwith " uhhh arr in obj " )
| Some Token . LBRACE -> ( match split_with ( list_skip tl 2 ) Token . LBRACE Token . RBRACE with
| Some ( arr , rest ) -> parse_object_i ( rest ) ( Map. set acc ~ key : i ~ data : ( parse_object arr ) )
| Some ( arr , rest ) -> parse_object_i ( rest ) ( Obj. add i ( parse_object arr ) acc )
| None -> failwith " uhhh arr in obj " )
| _ -> " TODO: Unhandled token for object value " ^ token_to_string hd ^ " ( " ^ print_token_array tl ^ " ) " | > failwith
| _ -> " TODO: Unhandled token for object value " ^ Token . token_to_string hd ^ " ( " ^ print_token_array tl ^ " ) " | > failwith
)
| Token . COMMA when not ( if_list_peek tl 0 Token . RBRACE ) -> parse_object_i tl acc
| Token . COMMA when if_list_peek tl 0 Token . RBRACE -> acc
| Token . RBRACE -> acc
| _ -> " TODO: Unhandled token in object: " ^ ( Token . token_to_string hd ) ^ " ( " ^ ( print_token_array tl ) ^ " ) " | > failwith )
| ( Some Token . RBRACE , _ ) -> acc
| _ -> ( String . concat ~ sep : " , " ( List . map ( Map . to_alist acc ) ~ f : ( fun ( k , v ) -> k ^ " : ( " ^ ( hvalue_to_string v ) ^ " ) " ) ) ) | > failwith
in OBJECT ( parse_object_i tokens ( Map. empty ( module String ) ) )
| _ -> ( String . concat " , " ( List . map ( fun ( k , v ) -> k ^ " : ( " ^ ( hvalue_to_string v ) ^ " ) " ) ( Obj . to_list acc ) ) ) | > failwith
in OBJECT ( parse_object_i tokens ( Obj. empty ) )
and parse_arr tokens =
let rec parse_arr_i tkns acc =
match safe_list tkns with
| ( Some hd , Some tl ) -> ( match hd with
| Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t -> ( match List . hd tl with
| Some Token . COMMA when List . length tl > = 2 -> parse_arr_i ( List . tl_exn tl ) ( ( parse_primitive t ) :: acc )
| Some Token . RBRACKET -> ( ( parse_primitive t ) :: acc )
| _ -> failwith " Invalid array "
| Token . INTEGER _ | Token . FLOAT _ | Token . STRING _ | Token . BINARY _ | Token . NULL as t -> ( match safe_list tl with
| ( Some Token . COMMA , Some tl ) -> ( match safe_hd tl with
| Some Token . EOF -> failwith " Unterminated Array "
| Some Token . RBRACKET -> ( ( parse_primitive t ) :: acc )
| _ -> parse_arr_i tl ( ( parse_primitive t ) :: acc )
)
| ( Some Token . RBRACKET , _ ) -> ( ( parse_primitive t ) :: acc )
| ( Some Token . EOF , _ ) -> failwith " Unterminated Array "
| _ -> " Invalid Array ( " ^ print_token_array tl ^ " ) " | > failwith
)
| Token . LBRACKET -> ( match split_with tl Token . LBRACKET Token . RBRACKET with
| Some ( arr , rest ) -> parse_arr_i ( rest ) ( parse_arr arr :: acc )
@ -138,6 +150,7 @@ module Parser = struct
| t -> " TODO: Unhandled token in array: " ^ ( Token . token_to_string t ) ^ " ( " ^ ( print_token_array tl ) ^ " ) " | > failwith
)
| ( Some Token . EOF , None ) -> acc
| ( Some Token . RBRACKET , None ) -> acc
| _ -> " TODO: parse_arr ( " ^ ( print_token_array tkns ) ^ " ) " | > failwith
in ARRAY ( List . rev ( parse_arr_i tokens [] ) )
end