hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mhare/lex/+test.ha | 4+++-
Mhare/lex/lex.ha | 38+++++++++++++++++++++++++++-----------
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"),