From 4651fadcea5108f011ac11b8f52debae9f784d59 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 22 Sep 2024 22:27:19 +0900 Subject: [PATCH] small change to support radixed number literals --- lib/read.c | 37 ++++++++++++++++++++++++------------- t/feed-01.hcl | 12 ++++++++++++ t/feed-5001.err | 4 ++++ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/read.c b/lib/read.c index 64d1673..cbe9c93 100644 --- a/lib/read.c +++ b/lib/read.c @@ -234,13 +234,21 @@ static HCL_INLINE int is_linebreak (hcl_ooci_t c) return c == '\n'; /* make sure this is one of the space chars in is_spacechar() */ } -static HCL_INLINE int is_digitchar (hcl_ooci_t c) +static HCL_INLINE int is_digit_char (hcl_ooci_t c) { /* TODO: support full unicode */ return (c >= '0' && c <= '9'); } -static HCL_INLINE int is_xdigitchar (hcl_ooci_t c) +static HCL_INLINE int is_radixed_digit_char (hcl_ooci_t c, int radix) +{ + if (c >= '0' && c <= '9') return (c - '0') < radix; + if (c >= 'a' && c <= 'z') return (c - 'a' + 10) < radix; + if (c >= 'A' && c <= 'Z') return (c - 'A' + 10) < radix; + return 0; +} + +static HCL_INLINE int is_xdigit_char (hcl_ooci_t c) { /* TODO: support full unicode */ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); @@ -1867,7 +1875,7 @@ static int feed_process_token (hcl_t* hcl) HCL_ASSERT (hcl, TOKEN_NAME_LEN(hcl) >= 3); for (i = 2; i < TOKEN_NAME_LEN(hcl); i++) { - HCL_ASSERT (hcl, is_xdigitchar(TOKEN_NAME_CHAR(hcl, i))); + HCL_ASSERT (hcl, is_xdigit_char(TOKEN_NAME_CHAR(hcl, i))); v = v * 16 + HCL_CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 16); } @@ -1889,7 +1897,7 @@ static int feed_process_token (hcl_t* hcl) HCL_ASSERT (hcl, TOKEN_NAME_LEN(hcl) >= 3); for (i = 2; i < TOKEN_NAME_LEN(hcl); i++) { - HCL_ASSERT (hcl, is_digitchar(TOKEN_NAME_CHAR(hcl, i))); + HCL_ASSERT (hcl, is_digit_char(TOKEN_NAME_CHAR(hcl, i))); v = v * 10 + HCL_CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 10); if (v > HCL_ERROR_MAX) @@ -2223,6 +2231,7 @@ static HCL_INLINE void init_flx_pn (hcl_flx_pn_t* pn, hcl_ooch_t start_digit) { HCL_MEMSET (pn, 0, HCL_SIZEOF(*pn)); pn->start_digit = start_digit; + pn->radix = 10; } static HCL_INLINE void init_flx_st (hcl_flx_st_t* st, hcl_ooch_t sign_c) @@ -2640,7 +2649,7 @@ static int flx_hmarked_char (hcl_t* hcl, hcl_ooci_t c) c = 0; for (i = 3; i < TOKEN_NAME_LEN(hcl); i++) { - if (!is_xdigitchar(TOKEN_NAME_CHAR(hcl, i))) + if (!is_xdigit_char(TOKEN_NAME_CHAR(hcl, i))) { hcl_setsynerrbfmt (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "invalid hexadecimal character character literal %.*js", TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); @@ -3015,7 +3024,7 @@ static int flx_plain_number (hcl_t* hcl, hcl_ooci_t c) /* number */ { hcl_flx_pn_t* pn = FLX_PN(hcl); - if (is_digitchar(c)) + if (is_radixed_digit_char(c, pn->radix)) { ADD_TOKEN_CHAR (hcl, c); pn->digit_count[pn->fpdec]++; @@ -3049,7 +3058,7 @@ static int flx_plain_number (hcl_t* hcl, hcl_ooci_t c) /* number */ { if (!pn->fpdec && c == '.') { - if (pn->radix) + if (pn->radix != 10) { hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, FLX_LOC(hcl), HCL_NULL, "invalid use of decimal point after radixed number '%.*js'", @@ -3063,19 +3072,21 @@ static int flx_plain_number (hcl_t* hcl, hcl_ooci_t c) /* number */ if (pn->digit_count[0] == 0) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl), - "invalid numeric literal with no digit before decimal point"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), HCL_NULL, + "invalid numeric literal with no digit '%.*js'", + TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); return -1; } else if (pn->fpdec && pn->digit_count[1] == 0) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl), - "invalid numeric literal with no digit after decimal point"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), HCL_NULL, + "invalid numeric literal with no digit after decimal point '%.*js'", + TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); return -1; } non_digit_char: - FEED_WRAP_UP (hcl, (pn->fpdec? HCL_TOK_FPDECLIT: (pn->radix? HCL_TOK_RADNUMLIT: HCL_TOK_NUMLIT))); + FEED_WRAP_UP (hcl, (pn->fpdec? HCL_TOK_FPDECLIT: (pn->radix != 10? HCL_TOK_RADNUMLIT: HCL_TOK_NUMLIT))); goto not_consumed; } @@ -3275,7 +3286,7 @@ static int flx_signed_token (hcl_t* hcl, hcl_ooci_t c) hcl_flx_st_t* st = FLX_ST(hcl); HCL_ASSERT (hcl, st->char_count == 0); - if (is_digitchar(c)) + if (is_digit_char(c)) { /* the sign is not part of the pn->digit_count[0] but is * in the current token buffer. pn->digit_count[0] doesn't diff --git a/t/feed-01.hcl b/t/feed-01.hcl index d71ca3f..5a54bf8 100644 --- a/t/feed-01.hcl +++ b/t/feed-01.hcl @@ -103,4 +103,16 @@ while (< i 52) { i := (+ i 1) } + +i := 0xAbCd93481FFAABBCCDDEeFa12837281 +j := 0o125715446440377652567463357357502240671201 +k := 0b1010101111001101100100110100100000011111111110101010101110111100110011011101111011101111101000010010100000110111001010000001 +l := 14272837210234798094990047170340811393 + +if (== i j) { printf "OK: i is equal to j\n" } \ +else { printf "ERROR: i is not equal to j\n" } +if (== i k) { printf "OK: i is equal to k\n" } \ +else { printf "ERROR: i is not equal to k\n" } +if (== i l) { printf "OK: i is equal to l\n" } \ +else { printf "ERROR: i is not equal to l\n" } } ## END diff --git a/t/feed-5001.err b/t/feed-5001.err index 4aa2438..2020317 100644 --- a/t/feed-5001.err +++ b/t/feed-5001.err @@ -14,6 +14,10 @@ $include 10 ##ERROR: syntax error - $include target expected in place of '10' --- +0b ##ERROR: invalid numeric literal with no digit '0b' + +--- + ## x := (+ 10 20) "aaaa"; ##ERROR: syntax error - too many rvalues