1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
type t = {
int: int option;
float: float option;
literal: string option;
}
let of_int n =
{ int = Some n; float = Some (Float.of_int n); literal = Some (string_of_int n) }
let of_float f =
let int_opt =
if Float.is_integer f then
(try
let n = int_of_float f in
if Float.of_int n = f then Some n else None
with _ -> None)
else None
in
{ int = int_opt; float = Some f; literal = None }
let json_number_re =
let open Re in
compile (whole_string (seq [
opt (char '-');
alt [char '0'; seq [rg '1' '9'; rep digit]];
opt (seq [char '.'; rep1 digit]);
opt (seq [set "eE"; opt (set "+-"); rep1 digit]);
]))
let is_valid_json_number s = Re.execp json_number_re s
let of_string_opt s =
if not (is_valid_json_number s) then None
else
let float_opt =
match float_of_string_opt s with
| Some f when not (Float.is_nan f) && not (Float.is_infinite f) -> Some f
| _ -> None
in
let int_opt = int_of_string_opt s in
Some { int = int_opt; float = float_opt; literal = Some s }
let of_int64 (i : int64) : t =
let n = Int64.to_int i in
if Int64.of_int n = i then of_int n
else
match of_string_opt (Int64.to_string i) with
| Some n -> n
| None ->
assert false