-module(gj_decode). -compile(no_auto_import). -export([decode/1]). decode(Str) -> State0 = {state, 0, 0, Str}, ParseResult = parse_value(State0), Final = case ParseResult of {State1, {ok, Val}} -> State2 = chomp_whitespace(State1), case next_grapheme(erlang:element(4, State2)) of {error, nil} -> {State2, {ok, Val}}; {ok, {C, _}} -> {State2, {error, {unexpected_token, C}}} end; _ -> ParseResult end, case Final of {_, {ok, V}} -> {ok, V}; {S, {error, Pe}} -> {error, {Pe, {parse_error_location, erlang:element(3, S), erlang:element(2, S)}}} end. parse_value(State0) -> State = chomp_whitespace(State0), ParseResult = case next_grapheme(erlang:element(4, State)) of {error, nil} -> {State, {error, unexpected_end_of_input}}; {ok, {C, Rest}} -> case C of <<"n"/utf8>> -> case pop_str(Rest, 3) of {ok, {[<<"u"/utf8>>, <<"l"/utf8>>, <<"l"/utf8>>], Rest1}} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 4 ), Rest1 ), {ok, null}}; _ -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; <<"t"/utf8>> -> case pop_str(Rest, 3) of {ok, {[<<"r"/utf8>>, <<"u"/utf8>>, <<"e"/utf8>>], Rest1@1}} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 4 ), Rest1@1 ), {ok, {boolean, true}}}; _ -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; <<"f"/utf8>> -> case pop_str(Rest, 4) of {ok, {[<<"a"/utf8>>, <<"l"/utf8>>, <<"s"/utf8>>, <<"e"/utf8>>], Rest1@2}} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 5 ), Rest1@2 ), {ok, {boolean, false}}}; _ -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; <<"["/utf8>> -> parse_array( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), a_value_or_end, [] ); <<"{"/utf8>> -> parse_object( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), o_key_or_end, [] ); <<"\""/utf8>> -> parse_string( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ) ); <<"-"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), leading_minus, gleam@bit_builder:from_string(C) ); <<"0"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), leading_zero, gleam@bit_builder:from_string(C) ); <<"1"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"2"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"3"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"4"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"5"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"6"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"7"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"8"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); <<"9"/utf8>> -> parse_number( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), whole, gleam@bit_builder:from_string(C) ); _ -> {State, {error, {unexpected_token, C}}} end end, ParseResult. parse_number(State0, Phase, Acc) -> CanEnd = case Phase of leading_zero -> true; whole -> true; decimal -> true; digit_or_end -> true; leading_minus -> false; decimal_init -> false; exponent_init -> false; number_error -> false; exponent_leading_sign -> false end, case next_grapheme(erlang:element(4, State0)) of {error, nil} -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json} -> {State0, {ok, Json}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; {ok, {C, Rest}} -> case C of <<" "/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; <<"\n"/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; <<"]"/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; <<"}"/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; <<","/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; <<"\t"/utf8>> -> case CanEnd of true -> case resolve_number(Acc) of {ok, Json@1} -> {State0, {ok, Json@1}}; {error, _} -> {State0, {error, invalid_number}} end; false -> {State0, {error, unexpected_end_of_input}} end; _ -> NewPhase = case Phase of leading_minus -> case C of <<"0"/utf8>> -> leading_zero; <<"1"/utf8>> -> whole; <<"2"/utf8>> -> whole; <<"3"/utf8>> -> whole; <<"4"/utf8>> -> whole; <<"5"/utf8>> -> whole; <<"6"/utf8>> -> whole; <<"7"/utf8>> -> whole; <<"8"/utf8>> -> whole; <<"9"/utf8>> -> whole; _ -> number_error end; leading_zero -> case C of <<"."/utf8>> -> decimal_init; <<"e"/utf8>> -> exponent_init; <<"E"/utf8>> -> exponent_init; _ -> number_error end; whole -> case C of <<"."/utf8>> -> decimal_init; <<"e"/utf8>> -> exponent_init; <<"E"/utf8>> -> exponent_init; <<"0"/utf8>> -> whole; <<"1"/utf8>> -> whole; <<"2"/utf8>> -> whole; <<"3"/utf8>> -> whole; <<"4"/utf8>> -> whole; <<"5"/utf8>> -> whole; <<"6"/utf8>> -> whole; <<"7"/utf8>> -> whole; <<"8"/utf8>> -> whole; <<"9"/utf8>> -> whole; _ -> number_error end; decimal_init -> case C of <<"0"/utf8>> -> decimal; <<"1"/utf8>> -> decimal; <<"2"/utf8>> -> decimal; <<"3"/utf8>> -> decimal; <<"4"/utf8>> -> decimal; <<"5"/utf8>> -> decimal; <<"6"/utf8>> -> decimal; <<"7"/utf8>> -> decimal; <<"8"/utf8>> -> decimal; <<"9"/utf8>> -> decimal; _ -> number_error end; decimal -> case C of <<"e"/utf8>> -> exponent_init; <<"E"/utf8>> -> exponent_init; <<"0"/utf8>> -> decimal; <<"1"/utf8>> -> decimal; <<"2"/utf8>> -> decimal; <<"3"/utf8>> -> decimal; <<"4"/utf8>> -> decimal; <<"5"/utf8>> -> decimal; <<"6"/utf8>> -> decimal; <<"7"/utf8>> -> decimal; <<"8"/utf8>> -> decimal; <<"9"/utf8>> -> decimal; _ -> number_error end; exponent_init -> case C of <<"+"/utf8>> -> exponent_leading_sign; <<"-"/utf8>> -> exponent_leading_sign; <<"0"/utf8>> -> digit_or_end; <<"1"/utf8>> -> digit_or_end; <<"2"/utf8>> -> digit_or_end; <<"3"/utf8>> -> digit_or_end; <<"4"/utf8>> -> digit_or_end; <<"5"/utf8>> -> digit_or_end; <<"6"/utf8>> -> digit_or_end; <<"7"/utf8>> -> digit_or_end; <<"8"/utf8>> -> digit_or_end; <<"9"/utf8>> -> digit_or_end; _ -> number_error end; exponent_leading_sign -> case C of <<"0"/utf8>> -> digit_or_end; <<"1"/utf8>> -> digit_or_end; <<"2"/utf8>> -> digit_or_end; <<"3"/utf8>> -> digit_or_end; <<"4"/utf8>> -> digit_or_end; <<"5"/utf8>> -> digit_or_end; <<"6"/utf8>> -> digit_or_end; <<"7"/utf8>> -> digit_or_end; <<"8"/utf8>> -> digit_or_end; <<"9"/utf8>> -> digit_or_end; _ -> number_error end; digit_or_end -> case C of <<"0"/utf8>> -> digit_or_end; <<"1"/utf8>> -> digit_or_end; <<"2"/utf8>> -> digit_or_end; <<"3"/utf8>> -> digit_or_end; <<"4"/utf8>> -> digit_or_end; <<"5"/utf8>> -> digit_or_end; <<"6"/utf8>> -> digit_or_end; <<"7"/utf8>> -> digit_or_end; <<"8"/utf8>> -> digit_or_end; <<"9"/utf8>> -> digit_or_end; _ -> number_error end; number_error -> number_error end, case NewPhase of number_error -> {State0, {error, {unexpected_token, C}}}; _ -> NewAcc = case {Phase, NewPhase, C} of {leading_zero, exponent_init, _} -> gleam@bit_builder:append_string( gleam@bit_builder:append_string( Acc, <<".0"/utf8>> ), C ); {whole, exponent_init, _} -> gleam@bit_builder:append_string( gleam@bit_builder:append_string( Acc, <<".0"/utf8>> ), C ); {exponent_init, exponent_leading_sign, <<"+"/utf8>>} -> Acc; {_, _, _} -> gleam@bit_builder:append_string(Acc, C) end, parse_number( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 1 ), Rest ), NewPhase, NewAcc ) end end end. parse_object(State0, Search, Stack) -> State = chomp_whitespace(State0), CanParseString = case Search of o_key -> true; o_key_or_end -> true; {o_colon, _} -> false; {o_value, _} -> false; o_comma_or_end -> false end, case next_grapheme(erlang:element(4, State)) of {error, nil} -> {State, {error, unexpected_end_of_input}}; {ok, {C, Rest}} -> case C of <<","/utf8>> -> case Search of o_comma_or_end -> parse_object( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), o_key, Stack ); {o_colon, _} -> {State, {error, {unexpected_token, C}}}; {o_value, _} -> {State, {error, {unexpected_token, C}}}; o_key_or_end -> {State, {error, {unexpected_token, C}}}; o_key -> {State, {error, {unexpected_token, C}}} end; <<"}"/utf8>> -> case Search of o_comma_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {ok, {object, gleam@list:reverse(Stack)}}}; o_key_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {ok, {object, gleam@list:reverse(Stack)}}}; {o_value, _} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; {o_colon, _} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_key -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; <<":"/utf8>> -> case Search of {o_colon, Str} -> parse_object( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {o_value, Str}, Stack ); {o_value, _} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_comma_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_key_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_key -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; <<"\""/utf8>> when CanParseString -> State1 = erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), case parse_string(State1) of {State2, {ok, {string, Str@1}}} -> parse_object(State2, {o_colon, Str@1}, Stack); Err -> Err end; _ -> case Search of {o_value, Key} -> case parse_value(State) of {State2@1, {ok, Json}} -> parse_object( State2@1, o_comma_or_end, [{Key, Json} | Stack] ); Err@1 -> Err@1 end; {o_colon, _} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_key -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_comma_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}}; o_key_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end end end. char_status(C) -> case gj_bridge:valid_in_string(C) of false -> not_allowed; true -> {allowed, C} end. parse_string(State0) -> do_parse_string(State0, gleam@bit_builder:from_string(<<""/utf8>>)). do_parse_string(State0, Acc) -> case next_grapheme(erlang:element(4, State0)) of {error, nil} -> {State0, {error, unexpected_end_of_input}}; {ok, {C, Rest}} -> case C of <<"\\"/utf8>> -> case next_grapheme(Rest) of {error, nil} -> {State0, {error, unexpected_end_of_input}}; {ok, {C2, Rest2}} -> Next = case C2 of <<"\""/utf8>> -> {add, <<"\""/utf8>>}; <<"/"/utf8>> -> {add, <<"/"/utf8>>}; <<"\\"/utf8>> -> {add, <<"\\"/utf8>>}; <<"b"/utf8>> -> {add, <<"\b"/utf8>>}; <<"f"/utf8>> -> {add, <<"\f"/utf8>>}; <<"n"/utf8>> -> {add, <<"\n"/utf8>>}; <<"r"/utf8>> -> {add, <<"\r"/utf8>>}; <<"t"/utf8>> -> {add, <<"\t"/utf8>>}; <<"u"/utf8>> -> {unicode, parse_unicode( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 2 ), Rest2 ) )}; _ -> invalid_escape end, case Next of {add, N} -> do_parse_string( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 2 ), Rest2 ), gleam@bit_builder:append_string(Acc, N) ); invalid_escape -> {State0, {error, {unexpected_token, C2}}}; {unicode, {State2, Uni}} -> case Uni of {ok, Str} -> do_parse_string( State2, gleam@bit_builder:append_string( Acc, Str ) ); {error, E} -> {State2, {error, E}} end end end; _ -> case char_status(C) of {allowed, <<"\""/utf8>>} -> case gleam@bit_string:to_string( gleam@bit_builder:to_bit_string(Acc) ) of {ok, Str@1} -> {erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 1 ), Rest ), {ok, {string, Str@1}}}; _ -> {State0, {error, invalid_string}} end; {allowed, _} -> do_parse_string( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 1 ), Rest ), gleam@bit_builder:append_string(Acc, C) ); not_allowed -> {State0, {error, {unexpected_token, C}}} end end end. parse_unicode(State0) -> case pop_str(erlang:element(4, State0), 4) of {ok, {[A, B, C, D], Rest}} -> case hex_to_unicode(A, B, C, D) of {ok, Uni} -> case gj_bridge:uni_to_bin([Uni]) of incomplete -> State = erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 4 ), Rest ), case pop_str(erlang:element(4, State), 6) of {ok, {[<<"\\"/utf8>>, <<"u"/utf8>>, E, F, G, H], Rest2}} -> case hex_to_unicode(E, F, G, H) of {ok, Uni2} -> case gj_bridge:uni_to_bin( [Uni, Uni2] ) of {complete, Str} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element( 2, State ) + 4 ), Rest2 ), {ok, Str}}; _ -> {State, {error, invalid_unicode_sequence}} end; {error, Int} -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + Int ), Rest ), {error, {unexpected_token, gleam@result:unwrap( gleam@list:at( [E, F, G, H], Int - 1 ), <<""/utf8>> )}}} end; _ -> {State, {error, unexpected_end_of_input}} end; nogood -> {State0, {error, invalid_unicode_sequence}}; {complete, Str@1} -> {erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 4 ), Rest ), {ok, Str@1}} end; {error, Int@1} -> {erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + Int@1 ), Rest ), {error, {unexpected_token, gleam@result:unwrap( gleam@list:at([A, B, C, D], Int@1 - 1), <<""/utf8>> )}}} end; _ -> {State0, {error, unexpected_end_of_input}} end. parse_array(State0, Search, Stack) -> State = chomp_whitespace(State0), case next_grapheme(erlang:element(4, State)) of {error, nil} -> {State, {error, unexpected_end_of_input}}; {ok, {C, Rest}} -> case C of <<","/utf8>> -> case Search of a_comma_or_end -> parse_array( erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), a_value, Stack ); a_value_or_end -> {State, {error, {unexpected_token, C}}}; a_value -> {State, {error, {unexpected_token, C}}} end; <<"]"/utf8>> -> case Search of a_comma_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {ok, {array, gleam@list:reverse(Stack)}}}; a_value_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {ok, {array, gleam@list:reverse(Stack)}}}; a_value -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end; _ -> case Search of a_value -> case parse_value(State) of {State1, {ok, Val}} -> parse_array( State1, a_comma_or_end, [Val | Stack] ); E -> E end; a_value_or_end -> case parse_value(State) of {State1, {ok, Val}} -> parse_array( State1, a_comma_or_end, [Val | Stack] ); E -> E end; a_comma_or_end -> {erlang:setelement( 4, erlang:setelement( 2, State, erlang:element(2, State) + 1 ), Rest ), {error, {unexpected_token, C}}} end end end. chomp_whitespace(State0) -> case next_grapheme(erlang:element(4, State0)) of {ok, {C, Rest}} -> case C of <<" "/utf8>> -> chomp_whitespace( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 1 ), Rest ) ); <<"\t"/utf8>> -> chomp_whitespace( erlang:setelement( 4, erlang:setelement( 2, State0, erlang:element(2, State0) + 1 ), Rest ) ); <<"\n"/utf8>> -> chomp_whitespace( {state, 0, erlang:element(3, State0) + 1, Rest} ); _ -> State0 end; {error, nil} -> State0 end. pop_str(Rest, N) -> pop_str_help(N, [], Rest). pop_str_help(N, Acc, Rest) -> case next_grapheme(Rest) of {ok, {C, Rest@1}} -> case N of 1 -> {ok, {gleam@list:reverse([C | Acc]), Rest@1}}; _ -> pop_str_help(N - 1, [C | Acc], Rest@1) end; _ -> {error, nil} end. hex_to_int(C) -> I = case C of <<"0"/utf8>> -> 0; <<"1"/utf8>> -> 1; <<"2"/utf8>> -> 2; <<"3"/utf8>> -> 3; <<"4"/utf8>> -> 4; <<"5"/utf8>> -> 5; <<"6"/utf8>> -> 6; <<"7"/utf8>> -> 7; <<"8"/utf8>> -> 8; <<"9"/utf8>> -> 9; <<"a"/utf8>> -> 10; <<"A"/utf8>> -> 10; <<"b"/utf8>> -> 11; <<"B"/utf8>> -> 11; <<"c"/utf8>> -> 12; <<"C"/utf8>> -> 12; <<"d"/utf8>> -> 13; <<"D"/utf8>> -> 13; <<"e"/utf8>> -> 14; <<"E"/utf8>> -> 14; <<"f"/utf8>> -> 15; <<"F"/utf8>> -> 15; _ -> 16 end, case I of 16 -> {error, nil}; X -> {ok, X} end. hex_to_unicode(A, B, C, D) -> case hex_to_int(A) of {error, _} -> {error, 1}; {ok, Aa} -> case hex_to_int(B) of {error, _} -> {error, 2}; {ok, Bb} -> case hex_to_int(C) of {error, _} -> {error, 3}; {ok, Cc} -> case hex_to_int(D) of {error, _} -> {error, 4}; {ok, Dd} -> <> = <>, {ok, <>} end end end end. resolve_number(Bb) -> Str = gleam@result:unwrap( gleam@bit_string:to_string(gleam@bit_builder:to_bit_string(Bb)), <<""/utf8>> ), case gleam@float:parse(Str) of {ok, F} -> {ok, {number, F}}; {error, _} -> case gleam@int:parse(Str) of {ok, I} -> {ok, {number, gleam@int:to_float(I)}}; {error, _} -> {error, nil} end end. next_grapheme(Str) -> gj_bridge:next_grapheme(Str).