authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 12:52:10-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 13:15:24-07:00
log2f15babbd35c8ba66261221dd345260cbfabe039
tree25998e31c6d86f4c947b7da3f6c862b74b1b7141
parentfe94ca8d1049c196d2db114562dc065ffc57b46c

better radix handling in float parsing. base 10 still doesn't work.


1 files changed, 59 insertions(+), 29 deletions(-)

src/parser.cpp+59-29
...@@ -585,10 +585,13 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool...@@ -585,10 +585,13 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool
585}585}
586586
587static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix,587static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix,
588 unsigned long long initial_value, bool *overflow) {588 int skip_index, bool *overflow)
589 unsigned long long x = initial_value;589{
590 unsigned long long x = 0;
590591
591 for (int i = digits_start; i < digits_end; i++) {592 for (int i = digits_start; i < digits_end; i++) {
593 if (i == skip_index)
594 continue;
592 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i);595 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i);
593 unsigned long long digit = get_digit_value(c);596 unsigned long long digit = get_digit_value(c);
594597
...@@ -625,7 +628,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -625,7 +628,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
625 if (token->decimal_point_pos == token->end_pos) {628 if (token->decimal_point_pos == token->end_pos) {
626 // integer629 // integer
627 unsigned long long whole_number = parse_int_digits(pc, whole_number_start, whole_number_end,630 unsigned long long whole_number = parse_int_digits(pc, whole_number_start, whole_number_end,
628 token->radix, 0, &num_lit->overflow);631 token->radix, -1, &num_lit->overflow);
629 if (num_lit->overflow) return;632 if (num_lit->overflow) return;
630633
631 num_lit->data.x_uint = whole_number;634 num_lit->data.x_uint = whole_number;
...@@ -641,12 +644,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -641,12 +644,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
641 }644 }
642 } else {645 } else {
643 // float646 // float
644 // TODO: trim leading and trailing zeros in the significand digit sequence
645 unsigned long long significand_as_int = parse_int_digits(pc, whole_number_start, whole_number_end,
646 token->radix, 0, &num_lit->overflow);
647 if (num_lit->overflow) return;
648
649 int exponent = 0;
650 if (token->decimal_point_pos < token->exponent_marker_pos) {647 if (token->decimal_point_pos < token->exponent_marker_pos) {
651 // fraction648 // fraction
652 int fraction_start = token->decimal_point_pos + 1;649 int fraction_start = token->decimal_point_pos + 1;
...@@ -655,15 +652,44 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -655,15 +652,44 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
655 // TODO: error for empty fraction part652 // TODO: error for empty fraction part
656 return;653 return;
657 }654 }
655 }
658656
659 // TODO: check for where the fraction got too precise instead of just saying overflow657 // trim leading and trailing zeros in the significand digit sequence
660 significand_as_int = parse_int_digits(pc, fraction_start, fraction_end,658 int significand_start = whole_number_start;
661 token->radix, significand_as_int, &num_lit->overflow);659 for (; significand_start < token->exponent_marker_pos; significand_start++) {
662 if (num_lit->overflow) return;660 if (significand_start == token->decimal_point_pos)
661 continue;
662 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + significand_start);
663 if (c != '0')
664 break;
665 }
666 int significand_end = token->exponent_marker_pos;
667 for (; significand_end - 1 > significand_start; significand_end--) {
668 if (significand_end - 1 <= token->decimal_point_pos) {
669 significand_end = token->decimal_point_pos;
670 break;
671 }
672 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + significand_end - 1);
673 if (c != '0')
674 break;
675 }
663676
664 // adjust the exponent to compensate for us effectively moving677 unsigned long long significand_as_int = parse_int_digits(pc, significand_start, significand_end,
665 // the decimal point all the way to the right678 token->radix, token->decimal_point_pos, &num_lit->overflow);
666 exponent = -(fraction_end - fraction_start);679 if (num_lit->overflow) return;
680
681 int exponent_in_bin_or_dec = 0;
682 if (significand_end > token->decimal_point_pos) {
683 exponent_in_bin_or_dec = token->decimal_point_pos + 1 - significand_end;
684 if (token->radix == 2) {
685 // already good
686 } else if (token->radix == 8) {
687 exponent_in_bin_or_dec *= 3;
688 } else if (token->radix == 10) {
689 // already good
690 } else if (token->radix == 16) {
691 exponent_in_bin_or_dec *= 4;
692 } else zig_unreachable();
667 }693 }
668694
669 if (token->exponent_marker_pos < token->end_pos) {695 if (token->exponent_marker_pos < token->end_pos) {
...@@ -674,7 +700,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -674,7 +700,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
674 // TODO: error for empty exponent part700 // TODO: error for empty exponent part
675 return;701 return;
676 }702 }
677
678 bool is_exponent_negative = false;703 bool is_exponent_negative = false;
679 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + exponent_start);704 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + exponent_start);
680 if (c == '+') {705 if (c == '+') {
...@@ -690,16 +715,17 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -690,16 +715,17 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
690 }715 }
691716
692 unsigned long long specified_exponent = parse_int_digits(pc, exponent_start, exponent_end,717 unsigned long long specified_exponent = parse_int_digits(pc, exponent_start, exponent_end,
693 10, 0, &num_lit->overflow);718 10, -1, &num_lit->overflow);
694 // TODO: this check is a little silly719 // TODO: this check is a little silly
695 if (specified_exponent >= LONG_LONG_MAX) {720 if (specified_exponent >= LONG_LONG_MAX) {
696 num_lit->overflow = true;721 num_lit->overflow = true;
697 return;722 return;
698 }723 }
724
699 if (is_exponent_negative) {725 if (is_exponent_negative) {
700 exponent -= specified_exponent;726 exponent_in_bin_or_dec -= specified_exponent;
701 } else {727 } else {
702 exponent += specified_exponent;728 exponent_in_bin_or_dec += specified_exponent;
703 }729 }
704 }730 }
705731
...@@ -707,16 +733,20 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -707,16 +733,20 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
707 uint64_t exponent_bits;733 uint64_t exponent_bits;
708 if (significand_as_int != 0) {734 if (significand_as_int != 0) {
709 // normalize the significand735 // normalize the significand
710 int significand_magnitude = __builtin_clzll(1) - __builtin_clzll(significand_as_int);736 if (token->radix == 10) {
711 exponent += significand_magnitude;737 zig_panic("TODO: decimal floats");
712 if (!(-1023 <= exponent && exponent < 1023)) {738 } else {
713 num_lit->overflow = true;739 int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand_as_int);
714 return;740 exponent_in_bin_or_dec += significand_magnitude_in_bin;
715 }741 if (!(-1023 <= exponent_in_bin_or_dec && exponent_in_bin_or_dec < 1023)) {
742 num_lit->overflow = true;
743 return;
744 }
716745
717 // this should chop off exactly one 1 bit from the top.746 // this should chop off exactly one 1 bit from the top.
718 significand_bits = ((uint64_t)significand_as_int << (52 - significand_magnitude)) & 0xfffffffffffffULL;747 significand_bits = ((uint64_t)significand_as_int << (52 - significand_magnitude_in_bin)) & 0xfffffffffffffULL;
719 exponent_bits = exponent + 1023;748 exponent_bits = exponent_in_bin_or_dec + 1023;
749 }
720 } else {750 } else {
721 // 0 is all 0's751 // 0 is all 0's
722 significand_bits = 0;752 significand_bits = 0;