diff --git a/lang/include/ivy/lang/lex.h b/lang/include/ivy/lang/lex.h index e670e84..52c5f8f 100644 --- a/lang/include/ivy/lang/lex.h +++ b/lang/include/ivy/lang/lex.h @@ -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; }; }; diff --git a/lang/lex.c b/lang/lex.c index bf460ce..a4d2566 100644 --- a/lang/lex.c +++ b/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. */ - 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);