commit 9048ce748f804c96ea61d27b2139edd8d4548428
parent 171bc0b0d1d5940b779ccab776bca38d4a59f639
Author: Sudipto Mallick <smlckz@disroot.org>
Date: Tue, 13 Apr 2021 12:56:23 +0000
lex: allow signed exponents for floating literals
Diffstat:
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/src/lex.c b/src/lex.c
@@ -304,7 +304,7 @@ lex_literal(struct lexer *lexer, struct token *out)
if (!strchr(basechrs, c)) {
switch (c) {
case '.':
- if (isfloat || suff) {
+ if (isfloat || suff || exp) {
push(lexer, c, true);
goto finalize;
}
@@ -322,7 +322,15 @@ lex_literal(struct lexer *lexer, struct token *out)
push(lexer, c, true);
goto finalize;
}
- exp = &lexer->buf[lexer->buflen];
+ // exponent is always in base 10
+ basechrs = "0123456789";
+ c = next(lexer, NULL, true);
+ if (c != '-' && c != '+' && !strchr(basechrs, c)) {
+ push(lexer, c, true);
+ push(lexer, 'e', true);
+ goto finalize;
+ };
+ exp = &lexer->buf[lexer->buflen - 1];
break;
case 'i':
case 'u':
@@ -382,11 +390,20 @@ finalize:
}
}
- uintmax_t exponent = 0;
+ intmax_t exponent = 0;
if (exp) {
char *endptr = NULL;
- exponent = strtoumax(exp, &endptr, 10);
- if (endptr == exp) {
+ exponent = strtoimax(exp, &endptr, 10);
+ // integers can't have negative exponents
+ if (exponent < 0 && !suff) {
+ out->storage = STORAGE_FCONST;
+ }
+ enum type_storage s = out->storage;
+ bool valid = exponent >= 0
+ || s == STORAGE_F32
+ || s == STORAGE_F64
+ || s == STORAGE_FCONST;
+ if (endptr == exp || !valid) {
out->token = T_ERROR;
consume(lexer, -1);
return out->token;
@@ -402,14 +419,14 @@ finalize:
case STORAGE_U64:
case STORAGE_SIZE:
out->uval = strtoumax(lexer->buf, NULL, base);
- for (uintmax_t i = 0; i < exponent; i++) {
+ for (intmax_t i = 0; i < exponent; i++) {
out->uval *= 10;
}
break;
case STORAGE_ICONST:
if (lexer->buf[0] != '-') {
uintmax_t uval = strtoumax(lexer->buf, NULL, base);
- for (uintmax_t i = 0; i < exponent; i++) {
+ for (intmax_t i = 0; i < exponent; i++) {
uval *= 10;
}
if (uval > (uintmax_t)INT64_MAX) {
@@ -425,7 +442,7 @@ finalize:
case STORAGE_INT:
case STORAGE_I64:
out->ival = strtoimax(lexer->buf, NULL, base);
- for (uintmax_t i = 0; i < exponent; i++) {
+ for (intmax_t i = 0; i < exponent; i++) {
out->ival *= 10;
}
break;
diff --git a/tests/00-constants.ha b/tests/00-constants.ha
@@ -8,4 +8,5 @@ export fn main() void = {
r6 = '\b', r7 = '\f', r8 = '\n', r9 = '\r', r10 = '\t',
r11 = '\v', r12 = '\\', r13 = '\'', r14 = '\"';
let f1 = 1.0, f2 = 1f32, f3 = 1.0e2, f4 = 1.0f64;
+ let f5 = 1.23e+45, f6 = 9.87e-65, f7 = 1e-7;
};