Add hex support

This commit is contained in:
Krzosa Karol
2022-06-13 22:14:31 +02:00
parent e73820c6f5
commit c0253f0424
5 changed files with 70 additions and 28 deletions

View File

@@ -37,6 +37,13 @@ lex_is_numeric(U8 c){
return result;
}
function B32
lex_is_numeric_base16(U8 c){
B32 result = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
return result;
}
function B32
lex_is_alphanumeric(U8 c){
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
@@ -73,20 +80,25 @@ token_error(Token *t, String error_val){
}
function void
lex_parse_u64(Lexer *lexer, Token *t){
lex_parse_u64(Lexer *lexer, Token *t, S64 base){
Scratch scratch;
Set_BigInt_Allocator(scratch);
t->kind = TK_Integer;
BigInt m = bigint_u64(1); // @leak, it accumulates and potentially needs allocation
BigInt val10 = bigint_u64(10);
BigInt m = bigint_u64(1);
BigInt base_mul = bigint_u64(base);
BigInt result = bigint_u64(0);
for(S64 i = t->len - 1; i >= 0; --i){
BigInt val = bigint_u64(t->str[i] - '0'); // I dont think this is a leak, too small
BigInt new_val = bigint_mul(&val, &m); // @leak
result = bigint_add(&result, &new_val); // @leak
m = bigint_mul(&m, &val10); // @leak
U64 value = t->str[i];
if(t->str[i] >= 'a') value = value - 'a' + 10;
else if(t->str[i] >= 'A') value = value - 'A' + 10;
else value -= '0';
BigInt val = bigint_u64(value);
BigInt new_val = bigint_mul(&val, &m);
result = bigint_add(&result, &new_val);
m = bigint_mul(&m, &base_mul);
}
t->int_val = bigint_copy(lexer->arena, &result);
@@ -475,7 +487,23 @@ lex__stream(Lexer *lexer){
}
} break;
case '0':case '1':case '2':case '3':case '4':
case '0':{
if(lexc(s) == 'x'){
lex_advance(s);
while(lex_is_numeric_base16(lexc(s)))
lex_advance(s);
lex_set_len(s, &t);
t.str += 2;
t.len -= 2;
if(t.len == 0)
token_error(&t, "Hex constant doesn't have value"_s);
else
lex_parse_u64(lexer, &t, 16);
break;
}
}
case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':{
B32 found_dot = false;
for(;;){
@@ -494,7 +522,7 @@ lex__stream(Lexer *lexer){
}
lex_set_len(s, &t);
if(found_dot) lex_parse_f64(&t);
else lex_parse_u64(lexer, &t);
else lex_parse_u64(lexer, &t, 10);
} break;