|
|
@@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|