diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-25 00:45:28 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-25 00:45:28 -0400 |
| commit | c6014873d83889e4bf598f6073c771480da20b7b (patch) | |
| tree | 8ddb39540764cd034d39dc915974510b00afe45a | |
| parent | aed80436a0a5eb12d9cace916167b0f7bd433589 (diff) | |
Split out number parsing
| -rw-r--r-- | src/parse/numbers.c | 83 | ||||
| -rw-r--r-- | src/parse/numbers.h | 10 | ||||
| -rw-r--r-- | src/parse/parse.c | 72 | ||||
| -rw-r--r-- | src/parse/parse.h | 2 |
4 files changed, 95 insertions, 72 deletions
diff --git a/src/parse/numbers.c b/src/parse/numbers.c new file mode 100644 index 00000000..a0db1273 --- /dev/null +++ b/src/parse/numbers.c @@ -0,0 +1,83 @@ + +#include <ctype.h> +#include <gc.h> +#include <stdarg.h> +#include <stdbool.h> +#include <string.h> + +#include <unictype.h> +#include <uniname.h> + +#include "../ast.h" +#include "../stdlib/util.h" +#include "context.h" +#include "errors.h" +#include "utils.h" + +static const double RADIANS_PER_DEGREE = 0.0174532925199432957692369076848861271344287188854172545609719144; + +public +ast_t *parse_int(parse_ctx_t *ctx, const char *pos) { + const char *start = pos; + (void)match(&pos, "-"); + if (!isdigit(*pos)) return NULL; + if (match(&pos, "0x")) { // Hex + pos += strspn(pos, "0123456789abcdefABCDEF_"); + } else if (match(&pos, "0b")) { // Binary + pos += strspn(pos, "01_"); + } else if (match(&pos, "0o")) { // Octal + pos += strspn(pos, "01234567_"); + } else { // Decimal + pos += strspn(pos, "0123456789_"); + } + char *str = GC_MALLOC_ATOMIC((size_t)(pos - start) + 1); + memset(str, 0, (size_t)(pos - start) + 1); + for (char *src = (char *)start, *dest = str; src < pos; ++src) { + if (*src != '_') *(dest++) = *src; + } + + if (match(&pos, "e") || match(&pos, "f")) // floating point literal + return NULL; + + if (match(&pos, "%")) { + double n = strtod(str, NULL) / 100.; + return NewAST(ctx->file, start, pos, Num, .n = n); + } else if (match(&pos, "deg")) { + double n = strtod(str, NULL) * RADIANS_PER_DEGREE; + return NewAST(ctx->file, start, pos, Num, .n = n); + } + + return NewAST(ctx->file, start, pos, Int, .str = str); +} + +public +ast_t *parse_num(parse_ctx_t *ctx, const char *pos) { + const char *start = pos; + bool negative = match(&pos, "-"); + if (!isdigit(*pos) && *pos != '.') return NULL; + else if (*pos == '.' && !isdigit(pos[1])) return NULL; + + size_t len = strspn(pos, "0123456789_"); + if (strncmp(pos + len, "..", 2) == 0) return NULL; + else if (pos[len] == '.') len += 1 + strspn(pos + len + 1, "0123456789"); + else if (pos[len] != 'e' && pos[len] != 'f' && pos[len] != '%') return NULL; + if (pos[len] == 'e') { + len += 1; + if (pos[len] == '-') len += 1; + len += strspn(pos + len, "0123456789_"); + } + char *buf = GC_MALLOC_ATOMIC(len + 1); + memset(buf, 0, len + 1); + for (char *src = (char *)pos, *dest = buf; src < pos + len; ++src) { + if (*src != '_') *(dest++) = *src; + } + double d = strtod(buf, NULL); + pos += len; + + if (negative) d *= -1; + + if (match(&pos, "%")) d /= 100.; + else if (match(&pos, "deg")) d *= RADIANS_PER_DEGREE; + + return NewAST(ctx->file, start, pos, Num, .n = d); +} diff --git a/src/parse/numbers.h b/src/parse/numbers.h new file mode 100644 index 00000000..89f5e28b --- /dev/null +++ b/src/parse/numbers.h @@ -0,0 +1,10 @@ +// Logic for parsing numbers +#pragma once + +// Parsing logic + +#include "../ast.h" +#include "context.h" + +ast_t *parse_int(parse_ctx_t *ctx, const char *pos); +ast_t *parse_num(parse_ctx_t *ctx, const char *pos); diff --git a/src/parse/parse.c b/src/parse/parse.c index 48c92ef9..53365ee7 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -1,5 +1,5 @@ // Recursive descent parser for parsing code -#include <ctype.h> + #include <gc.h> #include <stdarg.h> #include <stdbool.h> @@ -16,10 +16,10 @@ #include "context.h" #include "errors.h" #include "files.h" +#include "numbers.h" #include "parse.h" #include "utils.h" -static const double RADIANS_PER_DEGREE = 0.0174532925199432957692369076848861271344287188854172545609719144; static const char closing[128] = {['('] = ')', ['['] = ']', ['<'] = '>', ['{'] = '}'}; int op_tightness[] = { @@ -49,10 +49,6 @@ int op_tightness[] = { [Xor] = 1, }; -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// AST-based parsers ///////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - ast_t *parse_parens(parse_ctx_t *ctx, const char *pos) { const char *start = pos; spaces(&pos); @@ -75,39 +71,6 @@ ast_t *parse_parens(parse_ctx_t *ctx, const char *pos) { return new (ast_t, .file = (ctx)->file, .start = start, .end = pos, .tag = expr->tag, .__data = expr->__data); } -ast_t *parse_int(parse_ctx_t *ctx, const char *pos) { - const char *start = pos; - (void)match(&pos, "-"); - if (!isdigit(*pos)) return NULL; - if (match(&pos, "0x")) { // Hex - pos += strspn(pos, "0123456789abcdefABCDEF_"); - } else if (match(&pos, "0b")) { // Binary - pos += strspn(pos, "01_"); - } else if (match(&pos, "0o")) { // Octal - pos += strspn(pos, "01234567_"); - } else { // Decimal - pos += strspn(pos, "0123456789_"); - } - char *str = GC_MALLOC_ATOMIC((size_t)(pos - start) + 1); - memset(str, 0, (size_t)(pos - start) + 1); - for (char *src = (char *)start, *dest = str; src < pos; ++src) { - if (*src != '_') *(dest++) = *src; - } - - if (match(&pos, "e") || match(&pos, "f")) // floating point literal - return NULL; - - if (match(&pos, "%")) { - double n = strtod(str, NULL) / 100.; - return NewAST(ctx->file, start, pos, Num, .n = n); - } else if (match(&pos, "deg")) { - double n = strtod(str, NULL) * RADIANS_PER_DEGREE; - return NewAST(ctx->file, start, pos, Num, .n = n); - } - - return NewAST(ctx->file, start, pos, Int, .str = str); -} - type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) { const char *start = pos; if (!match(&pos, "{")) return NULL; @@ -230,37 +193,6 @@ type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos) { return type; } -ast_t *parse_num(parse_ctx_t *ctx, const char *pos) { - const char *start = pos; - bool negative = match(&pos, "-"); - if (!isdigit(*pos) && *pos != '.') return NULL; - else if (*pos == '.' && !isdigit(pos[1])) return NULL; - - size_t len = strspn(pos, "0123456789_"); - if (strncmp(pos + len, "..", 2) == 0) return NULL; - else if (pos[len] == '.') len += 1 + strspn(pos + len + 1, "0123456789"); - else if (pos[len] != 'e' && pos[len] != 'f' && pos[len] != '%') return NULL; - if (pos[len] == 'e') { - len += 1; - if (pos[len] == '-') len += 1; - len += strspn(pos + len, "0123456789_"); - } - char *buf = GC_MALLOC_ATOMIC(len + 1); - memset(buf, 0, len + 1); - for (char *src = (char *)pos, *dest = buf; src < pos + len; ++src) { - if (*src != '_') *(dest++) = *src; - } - double d = strtod(buf, NULL); - pos += len; - - if (negative) d *= -1; - - if (match(&pos, "%")) d /= 100.; - else if (match(&pos, "deg")) d *= RADIANS_PER_DEGREE; - - return NewAST(ctx->file, start, pos, Num, .n = d); -} - ast_t *parse_list(parse_ctx_t *ctx, const char *pos) { const char *start = pos; if (!match(&pos, "[")) return NULL; diff --git a/src/parse/parse.h b/src/parse/parse.h index 1e8c979f..fed78032 100644 --- a/src/parse/parse.h +++ b/src/parse/parse.h @@ -45,7 +45,6 @@ ast_t *parse_func_def(parse_ctx_t *ctx, const char *pos); ast_t *parse_heap_alloc(parse_ctx_t *ctx, const char *pos); ast_t *parse_if(parse_ctx_t *ctx, const char *pos); ast_t *parse_inline_c(parse_ctx_t *ctx, const char *pos); -ast_t *parse_int(parse_ctx_t *ctx, const char *pos); ast_t *parse_lambda(parse_ctx_t *ctx, const char *pos); ast_t *parse_lang_def(parse_ctx_t *ctx, const char *pos); ast_t *parse_extend(parse_ctx_t *ctx, const char *pos); @@ -53,7 +52,6 @@ ast_t *parse_namespace(parse_ctx_t *ctx, const char *pos); ast_t *parse_negative(parse_ctx_t *ctx, const char *pos); ast_t *parse_not(parse_ctx_t *ctx, const char *pos); ast_t *parse_none(parse_ctx_t *ctx, const char *pos); -ast_t *parse_num(parse_ctx_t *ctx, const char *pos); ast_t *parse_parens(parse_ctx_t *ctx, const char *pos); ast_t *parse_pass(parse_ctx_t *ctx, const char *pos); ast_t *parse_path(parse_ctx_t *ctx, const char *pos); |
