diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-06-01 12:36:44 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-06-01 12:53:26 +0200 |
commit | d99604749d658f5f344d53e77dd52fbb0f6d176c (patch) | |
tree | 2e60555dc4ce9e81b42b7556dd2e2491473f776c /lexer.c | |
parent | 9efbe183d7805eb60652a3745ec48cd32682ef8d (diff) |
syntax: adjust number literal parsing and string to number conversion
- Recognize new number literal prefixes `0o` and `0O` for octal as well
as `0b` and `0B` for binary number literals
- Treat number literals with leading zeros as octal while parsing but
as decimal ones on implicit number conversions, means `012` will yield
`10` while `+"012"` or `"012" + 0` will yield `12`
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lexer.c')
-rw-r--r-- | lexer.c | 34 |
1 files changed, 31 insertions, 3 deletions
@@ -696,10 +696,38 @@ is_numeric_char(uc_lexer_t *lex, char c) { char prev = lex->lookbehindlen ? lex->lookbehind[lex->lookbehindlen-1] : 0; - if ((prev == 'e' || prev == 'E') && (c == '-' || c == '+')) + switch (c|32) { + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return true; - return prev ? (isxdigit(c) || c == 'x' || c == 'X' || c == '.') : (isdigit(c) || c == '.'); + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'o': + case 'x': + /* require previous char, a number literal cannot start with these */ + return prev != 0; + + case '+': + case '-': + /* sign is only allowed after an exponent char */ + return (prev|32) == 'e'; + } + + return false; } static uc_token_t * @@ -713,7 +741,7 @@ parse_number(uc_lexer_t *lex) if (!buf_remaining(lex) || !is_numeric_char(lex, lex->bufstart[0])) { lookbehind_append(lex, "\0", 1); - nv = uc_number_parse(lex->lookbehind, &e); + nv = uc_number_parse_octal(lex->lookbehind, &e); switch (ucv_type(nv)) { case UC_DOUBLE: |