lang: lex: implement lexing of decimal numbers

This commit is contained in:
2024-11-19 16:57:20 +00:00
parent a54a232428
commit 6e642b3c19
2 changed files with 60 additions and 13 deletions

View File

@@ -10,7 +10,8 @@ enum ivy_token_type {
IVY_TOK_KEYWORD,
IVY_TOK_SYMBOL,
IVY_TOK_ATOM,
IVY_TOK_NUMBER,
IVY_TOK_INT,
IVY_TOK_DOUBLE,
IVY_TOK_LABEL,
IVY_TOK_IDENT,
IVY_TOK_STRING,
@@ -104,7 +105,8 @@ struct ivy_token {
union {
enum ivy_keyword t_keyword;
enum ivy_symbol t_symbol;
unsigned long long t_number;
unsigned long long t_int;
double t_double;
char *t_str;
};
};

View File

@@ -537,7 +537,7 @@ static enum ivy_status push_atom(struct ivy_lexer *lex, char *s)
return push_token(lex, tok);
}
static enum ivy_status push_number(struct ivy_lexer *lex, unsigned long long v)
static enum ivy_status push_int(struct ivy_lexer *lex, unsigned long long v)
{
struct ivy_token *tok = malloc(sizeof *tok);
if (!tok) {
@@ -546,8 +546,22 @@ static enum ivy_status push_number(struct ivy_lexer *lex, unsigned long long v)
memset(tok, 0x0, sizeof *tok);
tok->t_type = IVY_TOK_NUMBER;
tok->t_number = v;
tok->t_type = IVY_TOK_INT;
tok->t_int = v;
return push_token(lex, tok);
}
static enum ivy_status push_double(struct ivy_lexer *lex, double v)
{
struct ivy_token *tok = malloc(sizeof *tok);
if (!tok) {
return IVY_ERR_NO_MEMORY;
}
memset(tok, 0x0, sizeof *tok);
tok->t_type = IVY_TOK_DOUBLE;
tok->t_double = v;
return push_token(lex, tok);
}
@@ -784,6 +798,7 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
{
int token_len = 0;
int base = 10;
int dots = 0;
b_string *str = get_temp_string(lex);
while (true) {
@@ -802,6 +817,23 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
continue;
}
if (c == '.' && iswdigit(peek_next(lex))) {
if (base != 10) {
return IVY_ERR_BAD_SYNTAX;
}
if (dots > 0) {
return IVY_ERR_BAD_SYNTAX;
}
token_len++;
dots++;
char s[] = {c, 0};
b_string_append_cstr(str, s);
advance(lex);
continue;
}
if (isspace(c) || ispunct(c)) {
break;
}
@@ -845,21 +877,33 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
}
if (token_len == 1 && base == 7) {
return push_number(lex, 0);
return push_int(lex, 0);
}
const char *s = b_string_ptr(str);
char *ep;
char *ep = NULL;
/* negative numbers will be lexed as a hyphen followed by a positive
* number. */
unsigned long long v = strtoull(s, &ep, base);
if (*ep != '\0') {
return IVY_ERR_BAD_SYNTAX;
if (dots > 0) {
double v = strtod(s, &ep);
if (*ep != '\0') {
return IVY_ERR_BAD_SYNTAX;
}
return push_double(lex, v);
} else {
unsigned long long v = strtoull(s, &ep, base);
if (*ep != '\0') {
return IVY_ERR_BAD_SYNTAX;
}
return push_int(lex, v);
}
return push_number(lex, v);
}
static enum ivy_status read_ident(struct ivy_lexer *lex)
@@ -1028,7 +1072,8 @@ const char *ivy_lex_token_type_to_string(enum ivy_token_type type)
ENUM_STR(IVY_TOK_KEYWORD);
ENUM_STR(IVY_TOK_SYMBOL);
ENUM_STR(IVY_TOK_ATOM);
ENUM_STR(IVY_TOK_NUMBER);
ENUM_STR(IVY_TOK_INT);
ENUM_STR(IVY_TOK_DOUBLE);
ENUM_STR(IVY_TOK_LABEL);
ENUM_STR(IVY_TOK_IDENT);
ENUM_STR(IVY_TOK_STRING);