MVMnum64 MVM_coerce_s_n(MVMThreadContext *tc, MVMString *s) { char *enc = MVM_string_ascii_encode(tc, s, NULL); MVMnum64 n; if (strcmp(enc, "NaN") == 0) n = MVM_num_nan(tc); else if (strcmp(enc, "Inf") == 0) n = MVM_num_posinf(tc); else if (strcmp(enc, "+Inf") == 0) n = MVM_num_posinf(tc); else if (strcmp(enc, "-Inf") == 0) n = MVM_num_neginf(tc); else n = atof(enc); MVM_free(enc); return n; }
static double parse_simple_number(MVMThreadContext *tc, MVMCodepointIter *ci, MVMCodepoint *cp, MVMString *s) { double sign; /* Handle NaN here, to make later parsing simpler */ if (match_word(tc, ci, cp, "NaN", s)) { return MVM_num_nan(tc); } sign = parse_sign(tc, ci, cp); if (match_word(tc, ci, cp, "Inf", s)) { return sign * MVM_num_posinf(tc); } else if (*cp == ':') { int radix; double body; get_cp(tc, ci, cp); radix = (int) parse_int_frac_exp(tc, ci, cp, s, 10, 0); if (*cp == '<') { get_cp(tc, ci, cp); body = parse_int_frac_exp(tc, ci, cp, s, radix, 0); if (*cp == '>') { /* > */ get_cp(tc, ci, cp); return sign * body; } parse_error(tc, s, "malformed ':radix<>' style radix number, expecting '>' after the body"); } else if (*cp == 171) { /* « */ get_cp(tc, ci, cp); body = parse_int_frac_exp(tc, ci, cp, s, radix, 0); if (*cp == 187) { /* » */ get_cp(tc, ci, cp); return sign * body; } parse_error(tc, s, "malformed ':radix«»' style radix number, expecting '>' after the body"); } else if (*cp == '[') { double result = 0; get_cp(tc, ci, cp); while (*cp != ']' && MVM_string_ci_has_more(tc, ci)) { double digit = parse_decimal_integer(tc, ci, cp, s); result = result * radix + digit; if (*cp == ',') { get_cp(tc, ci, cp); } } if (*cp == ']') { get_cp(tc, ci, cp); return sign * result; } parse_error(tc, s, "malformed ':radix[]' style radix number, expecting ']' after the body"); } parse_error(tc, s, "malformed ':radix' style number. Expected <, [ or « after ':radix'"); } else if (*cp == '0') { int radix = 0; get_cp(tc, ci, cp); switch (*cp) { case 'b': radix = 2; break; case 'o': radix = 8; break; case 'd': radix = 10; break; case 'x': radix = 16; break; } if (radix) { get_cp(tc, ci, cp); if (*cp == '_') get_cp(tc, ci, cp); return sign * parse_int_frac_exp(tc, ci, cp, s, radix, 1); } return sign * parse_int_frac_exp(tc, ci, cp, s, 10, 1); } else { return sign * parse_int_frac_exp(tc, ci, cp, s, 10, 0); } }