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_KEYWORD,
|
||||||
IVY_TOK_SYMBOL,
|
IVY_TOK_SYMBOL,
|
||||||
IVY_TOK_ATOM,
|
IVY_TOK_ATOM,
|
||||||
IVY_TOK_NUMBER,
|
IVY_TOK_INT,
|
||||||
|
IVY_TOK_DOUBLE,
|
||||||
IVY_TOK_LABEL,
|
IVY_TOK_LABEL,
|
||||||
IVY_TOK_IDENT,
|
IVY_TOK_IDENT,
|
||||||
IVY_TOK_STRING,
|
IVY_TOK_STRING,
|
||||||
@@ -104,7 +105,8 @@ struct ivy_token {
|
|||||||
union {
|
union {
|
||||||
enum ivy_keyword t_keyword;
|
enum ivy_keyword t_keyword;
|
||||||
enum ivy_symbol t_symbol;
|
enum ivy_symbol t_symbol;
|
||||||
unsigned long long t_number;
|
unsigned long long t_int;
|
||||||
|
double t_double;
|
||||||
char *t_str;
|
char *t_str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
67
lang/lex.c
67
lang/lex.c
@@ -537,7 +537,7 @@ static enum ivy_status push_atom(struct ivy_lexer *lex, char *s)
|
|||||||
return push_token(lex, tok);
|
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);
|
struct ivy_token *tok = malloc(sizeof *tok);
|
||||||
if (!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);
|
memset(tok, 0x0, sizeof *tok);
|
||||||
|
|
||||||
tok->t_type = IVY_TOK_NUMBER;
|
tok->t_type = IVY_TOK_INT;
|
||||||
tok->t_number = v;
|
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);
|
return push_token(lex, tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,6 +798,7 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
|
|||||||
{
|
{
|
||||||
int token_len = 0;
|
int token_len = 0;
|
||||||
int base = 10;
|
int base = 10;
|
||||||
|
int dots = 0;
|
||||||
b_string *str = get_temp_string(lex);
|
b_string *str = get_temp_string(lex);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -802,6 +817,23 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
|
|||||||
continue;
|
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)) {
|
if (isspace(c) || ispunct(c)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -845,21 +877,33 @@ static enum ivy_status read_number(struct ivy_lexer *lex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (token_len == 1 && base == 7) {
|
if (token_len == 1 && base == 7) {
|
||||||
return push_number(lex, 0);
|
return push_int(lex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *s = b_string_ptr(str);
|
const char *s = b_string_ptr(str);
|
||||||
char *ep;
|
char *ep = NULL;
|
||||||
|
|
||||||
/* negative numbers will be lexed as a hyphen followed by a positive
|
/* negative numbers will be lexed as a hyphen followed by a positive
|
||||||
* number. */
|
* number. */
|
||||||
unsigned long long v = strtoull(s, &ep, base);
|
|
||||||
|
|
||||||
if (*ep != '\0') {
|
if (dots > 0) {
|
||||||
return IVY_ERR_BAD_SYNTAX;
|
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)
|
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_KEYWORD);
|
||||||
ENUM_STR(IVY_TOK_SYMBOL);
|
ENUM_STR(IVY_TOK_SYMBOL);
|
||||||
ENUM_STR(IVY_TOK_ATOM);
|
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_LABEL);
|
||||||
ENUM_STR(IVY_TOK_IDENT);
|
ENUM_STR(IVY_TOK_IDENT);
|
||||||
ENUM_STR(IVY_TOK_STRING);
|
ENUM_STR(IVY_TOK_STRING);
|
||||||
|
|||||||
Reference in New Issue
Block a user