lang: lex: implement lexing of decimal numbers
This commit is contained in:
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
59
lang/lex.c
59
lang/lex.c
@@ -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. */
|
||||
|
||||
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_number(lex, v);
|
||||
return push_int(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);
|
||||
|
||||
Reference in New Issue
Block a user