diff options
Diffstat (limited to 'src/lexer.c')
-rw-r--r-- | src/lexer.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/lexer.c b/src/lexer.c index 09a1a31..ed2414a 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,4 +1,5 @@ #include <assert.h> +#include <ctype.h> #include <errno.h> #include <inttypes.h> #include <limits.h> @@ -37,7 +38,7 @@ static bool skip_comment(const uchar **ptr, const uchar *end) static const bool is_numeric_lookup[UCHAR_MAX + 1] = { ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, ['5'] = true, ['6'] = true, ['7'] = true, - ['8'] = true, ['9'] = true, ['\''] = true, + ['8'] = true, ['9'] = true, ['\''] = true, ['.'] = true, }; lexemes_t @@ -105,18 +106,28 @@ lexstring(const uchar *code, size_t codesz) break; case '.': - if (unlikely(end - code < 2) || code[0] != '.' || code[1] != '.') + if (unlikely(end - code < 2) || code[0] != '.' || code[1] != '.') { + if (likely(end - code) >= 1 && isdigit(code[0])) + goto number; goto fallback; + } code += 2; data.kinds[data.len++] = LEXELIP; break; case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '5': case '6': case '7': case '8': case '9': { +number: + bool saw_dot = false; data.kinds[data.len] = LEXNUM; data.strs[data.len].p = spnbeg; while (likely(code < end) && is_numeric_lookup[code[0]]) { + if (unlikely(code[0] == '.')) { + if (saw_dot) + err("lexer: Decimal separator given multiple times in numeric literal"); + saw_dot = true; + } if (unlikely(code[0] == '\'' && code[-1] == '\'')) { err("Adjacent numeric separators at byte %td", code - start); @@ -130,10 +141,11 @@ lexstring(const uchar *code, size_t codesz) data.strs[data.len++].len = code - spnbeg; break; + } default: fallback: - if (!rune_is_xids(ch)) + if (unlikely(!rune_is_xids(ch))) err("lexer: Unexpected rune U+%04" PRIXRUNE, ch); data.kinds[data.len] = LEXIDENT; |