Browse Source

float literals

master
Martin Dørum 9 months ago
parent
commit
c3042c48fc
1 changed files with 60 additions and 30 deletions
  1. 60
    30
      lib/parse/lex.c

+ 60
- 30
lib/parse/lex.c View File

@@ -23,22 +23,16 @@ static void log_token(struct l2_token *tok) {
}
}

static int parse_number(const char *str, double *num) {
// TODO: Floats
size_t len = strlen(str);
*num = 0;
int power = 1;
for (int i = (int)len - 1; i >= 0; --i) {
static long long parse_integer(const char *str, size_t len) {
long long num = 0;
long long power = 1;
for (ssize_t i = len - 1; (ssize_t)i >= 0; --i) {
char ch = str[i];
if (ch >= '0' && ch <= '9') {
*num += (ch - '0') * power;
power *= 10;
} else {
return -1;
}
num += (ch - '0') * power;
power *= 10;
}

return 0;
return num;
}

const char *l2_token_kind_name(enum l2_token_kind kind) {
@@ -153,22 +147,61 @@ static int skip_whitespace(struct l2_lexer *lexer) {
return nl;
}

static int read_integer(struct l2_lexer *lexer) {
char buffer[16]; // Should be enough
static long long read_integer(struct l2_lexer *lexer) {
char buffer[32]; // Should be enough
size_t len = 0;

while (len < sizeof(buffer) - 1 && is_numeric(peek_ch(lexer))) {
while (len < sizeof(buffer) && is_numeric(peek_ch(lexer))) {
buffer[len++] = read_ch(lexer);
}

int num = 0;
int power = 1;
for (int i = len - 1; i >= 0; --i) {
num += (buffer[i] - '0') * power;
power *= 10;
return parse_integer(buffer, len);
}

static void read_number(struct l2_lexer *lexer, struct l2_token *tok) {
tok->kind = L2_TOK_NUMBER;

float sign = 1;
if (peek_ch(lexer) == '-') {
sign = -1;
read_ch(lexer);
}

return num;
if (!is_numeric(peek_ch(lexer))) {
tok->kind = L2_TOK_ERROR;
tok->v.str = "No number in number literal";
return;
}

long long integral = read_integer(lexer);
if (peek_ch(lexer) != '.') {
tok->v.num = (double)integral * sign;
return;
}

read_ch(lexer); // '.'

if (!is_numeric(peek_ch(lexer))) {
tok->kind = L2_TOK_ERROR;
tok->v.str = "Trailing dot in number literal";
return;
}

char buffer[32];
size_t fraction_len = 0;
while (fraction_len < sizeof(buffer) && is_numeric(peek_ch(lexer))) {
buffer[fraction_len++] = read_ch(lexer);
}

long long fraction = 0;
long long fraction_power = 1;
for (ssize_t i = fraction_len - 1; (ssize_t)i >= 0; --i) {
fraction += (buffer[i] - '0') * fraction_power;
fraction_power *= 10;
}

double num = (double)integral + ((double)fraction / (double)fraction_power);
tok->v.num = num * sign;
}

static void read_string(struct l2_lexer *lexer, struct l2_token *tok) {
@@ -392,18 +425,15 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {
break;

default:
read_ident(lexer, tok);
if (tok->kind != L2_TOK_IDENT) {
if (is_numeric(ch) || ch == '-') {
read_number(lexer, tok);
break;
}

double num;
if (parse_number(tok->v.str, &num) >= 0) {
free(tok->v.str);
tok->kind = L2_TOK_NUMBER;
tok->v.num = num;
read_ident(lexer, tok);
if (tok->kind != L2_TOK_IDENT) {
break;
}
break;
}
}


Loading…
Cancel
Save