commit 76c849125028969dbbcb70f6bb17d828241e8a99
parent 388150902e42e135401a2af61fe02784d82f0fba
Author: Sudipto Mallick <smlckz@disroot.org>
Date: Fri, 7 May 2021 13:07:37 +0000
hare::lex: fix exponent of floating-point literal
* allowing sign of exponent and uppercase exponent character 'E'
* unnecessary exponent calculation for floats, already handled in
stof64
Signed-off-by: Sudipto Mallick <smlckz@disroot.org>
Diffstat:
2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/hare/lex/+test.ha b/hare/lex/+test.ha
@@ -248,7 +248,7 @@ fn loc(line: uint, col: uint) location = location {
const in = "1e5 -1i32 9223372036854775809 1e2z 255u8 0o42u16\n"
"0b1000101u32 0xDEADBEEFu64 -0b10i8 -5e0i16 -0o16i32\n"
"0b00000010000001100000011100001111000000100000011000000111i64\n"
- "13.37 13.37f32 13.37f64";
+ "13.37 13.37f32 13.37f64 6.022e23 1.616255e-35f64";
const expected: [_]token = [
(ltok::LIT_ICONST, 1e5i64, loc(1, 1)),
(ltok::LIT_I32, -1i64, loc(1, 5)),
@@ -265,6 +265,8 @@ fn loc(line: uint, col: uint) location = location {
(ltok::LIT_FCONST, 13.37, loc(4, 1)),
(ltok::LIT_F32, 13.37, loc(4, 7)),
(ltok::LIT_F64, 13.37, loc(4, 16)),
+ (ltok::LIT_FCONST, 6.022e23, loc(4, 25)),
+ (ltok::LIT_F64, 1.616255e-35, loc(4, 34)),
];
lextest(in, expected);
};
diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha
@@ -352,13 +352,23 @@ fn lex_literal(lex: *lexer, loc: location) (token | error) = {
float = true;
append(chars, utf8::encoderune('.')...);
},
- 'e' => if (exp is size || suff is size || base != 10) {
+ 'e', 'E' => if (exp is size || suff is size || base != 10) {
unget(lex, r);
break;
} else {
if (end == 0) end = len(chars);
append(chars, utf8::encoderune(r)...);
exp = len(chars);
+ r = match (next(lex)?) {
+ io::EOF => break,
+ r: rune => r,
+ };
+ switch (r) {
+ '+', '-' => append(chars,
+ utf8::encoderune(r)...),
+ * => unget(lex, r),
+ };
+ basechrs = "0123456789";
},
'i', 'u', 'f', 'z' => if (suff is size) {
unget(lex, r);
@@ -387,13 +397,17 @@ fn lex_literal(lex: *lexer, loc: location) (token | error) = {
strings::fromutf8(chars[exp..end]);
},
};
- let exp = match (strconv::stoz(exp)) {
- exp: size => exp,
+ let exp = match (strconv::stoi(exp)) {
+ exp: int => exp,
strconv::invalid => abort(), // Shouldn't be lexed in
strconv::overflow =>
return syntaxerr(loc, "overflow in exponent"),
};
+ let floatend = match (suff) {
+ suff: size => suff,
+ void => len(chars),
+ };
let suff = match (suff) {
suff: size => strings::fromutf8(chars[suff..]),
void => "",
@@ -415,6 +429,12 @@ fn lex_literal(lex: *lexer, loc: location) (token | error) = {
else if (suff == "" && float) ltok::LIT_FCONST
else return syntaxerr(loc, "invalid literal suffix");
+ let exp = if (exp < 0) switch (suff) {
+ ltok::LIT_F32, ltok::LIT_F64, ltok::LIT_FCONST => exp: size,
+ * => return syntaxerr(loc,
+ "invalid negative exponent of integer"),
+ } else exp: size;
+
let val = strings::fromutf8(chars[..end]);
let val = switch (suff) {
ltok::LIT_U8, ltok::LIT_U16, ltok::LIT_U32, ltok::LIT_U64,
@@ -429,8 +449,10 @@ fn lex_literal(lex: *lexer, loc: location) (token | error) = {
},
ltok::LIT_I8, ltok::LIT_I16, ltok::LIT_I32, ltok::LIT_I64,
ltok::LIT_INT => strconv::stoi64b(val, base),
- ltok::LIT_F32, ltok::LIT_F64, ltok::LIT_FCONST =>
- strconv::stof64(val),
+ ltok::LIT_F32, ltok::LIT_F64, ltok::LIT_FCONST => {
+ val = strings::fromutf8(chars[..floatend]);
+ strconv::stof64(val);
+ },
};
let val = match (val) {
val: u64 => {
@@ -445,12 +467,6 @@ fn lex_literal(lex: *lexer, loc: location) (token | error) = {
};
val;
},
- val: f64 => {
- for (let i = 0z; i < exp; i += 1) {
- val *= 10.0;
- };
- val;
- },
strconv::invalid => abort(), // Shouldn't be lexed in
strconv::overflow =>
return syntaxerr(loc, "overflow in exponent"),