authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 14:54:16-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 14:54:16-07:00
log8a570c458bcf62bc3d882f8d253f75ec6d3fd719
tree2689c80e82a1a0a197af405a51fcd8f9c35296fb
parent43099932d55c7fa6279cba61eeba91c89a9cb1a0

base 10 decimals work now. closes #15


2 files changed, 44 insertions(+), 2 deletions(-)

src/parser.cpp+23-2
......@@ -12,7 +12,7 @@
1212#include <stdarg.h>
1313#include <stdio.h>
1414#include <limits.h>
15
15#include <errno.h>
1616
1717static const char *bin_op_str(BinOpType bin_op) {
1818 switch (bin_op) {
......@@ -622,6 +622,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
622622 int whole_number_end = token->decimal_point_pos;
623623 if (whole_number_end <= whole_number_start) {
624624 // TODO: error for empty whole number part
625 num_lit->overflow = true;
625626 return;
626627 }
627628
......@@ -644,12 +645,31 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
644645 }
645646 } else {
646647 // float
648
649 if (token->radix == 10) {
650 // use a third-party base-10 float parser
651 char *str_begin = buf_ptr(pc->buf) + whole_number_start;
652 char *str_end;
653 errno = 0;
654 double x = strtod(str_begin, &str_end);
655 if (errno) {
656 // TODO: forward error to user
657 num_lit->overflow = true;
658 return;
659 }
660 assert(str_end == buf_ptr(pc->buf) + token->end_pos);
661 num_lit->data.x_float = x;
662 num_lit->kind = NumLitF64;
663 return;
664 }
665
647666 if (token->decimal_point_pos < token->exponent_marker_pos) {
648667 // fraction
649668 int fraction_start = token->decimal_point_pos + 1;
650669 int fraction_end = token->exponent_marker_pos;
651670 if (fraction_end <= fraction_start) {
652671 // TODO: error for empty fraction part
672 num_lit->overflow = true;
653673 return;
654674 }
655675 }
......@@ -698,6 +718,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
698718 int exponent_end = token->end_pos;
699719 if (exponent_end <= exponent_start) {
700720 // TODO: error for empty exponent part
721 num_lit->overflow = true;
701722 return;
702723 }
703724 bool is_exponent_negative = false;
......@@ -711,6 +732,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
711732
712733 if (exponent_end <= exponent_start) {
713734 // TODO: error for empty exponent part
735 num_lit->overflow = true;
714736 return;
715737 }
716738
......@@ -754,7 +776,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
754776 }
755777
756778 uint64_t double_bits = (exponent_bits << 52) | significand_bits;
757 // TODO: check and swap endian
758779 double x = *(double *)&double_bits;
759780
760781 num_lit->data.x_float = x;
test/run_tests.cpp+21
......@@ -474,6 +474,20 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
474474 0.000000000000000000000000000000000000000000000000000000000e0 as f64);
475475 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
476476 0.0e000000000000000000000000000000000000000000000000000000000 as f64);
477 printf(c"1.0: %a\n",
478 1.0 as f64);
479 printf(c"10.0: %a\n",
480 10.0 as f64);
481 printf(c"10.5: %a\n",
482 10.5 as f64);
483 printf(c"10.5e5: %a\n",
484 10.5e5 as f64);
485 printf(c"10.5e+5: %a\n",
486 10.5e+5 as f64);
487 printf(c"50.0e-2: %a\n",
488 50.0e-2 as f64);
489 printf(c"50e-2: %a\n",
490 50e-2 as f64);
477491
478492 printf(c"\n");
479493
......@@ -524,6 +538,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
524538000000000000000000000000000000000000000000000000000000000.0e0: 0x0p+0
5255390.000000000000000000000000000000000000000000000000000000000e0: 0x0p+0
5265400.0e000000000000000000000000000000000000000000000000000000000: 0x0p+0
5411.0: 0x1p+0
54210.0: 0x1.4p+3
54310.5: 0x1.5p+3
54410.5e5: 0x1.0059p+20
54510.5e+5: 0x1.0059p+20
54650.0e-2: 0x1p-1
54750e-2: 0x1p-1
527548
5285490x1.0: 0x1p+0
5295500x10.0: 0x1p+4