diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..7899a42 --- /dev/null +++ b/.clang-format @@ -0,0 +1,26 @@ +UseTab: ForIndentation +TabWidth: 4 +IndentWidth: 4 +ColumnLimit: 80 + +AlignEscapedNewlines: DontAlign +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +BasedOnStyle: WebKit +BraceWrapping: + AfterFunction: true +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: true +BreakConstructorInitializers: BeforeComma +IndentPPDirectives: AfterHash +IndentRequiresClause: false +InsertNewlineAtEOF: true +LineEnding: LF +NamespaceIndentation: None +PointerAlignment: Right # east pointer +QualifierAlignment: Right # east const +RemoveSemicolon: true +RequiresClausePosition: WithFollowing +RequiresExpressionIndentation: OuterScope +SpaceAfterTemplateKeyword: false diff --git a/include/dcfg.h b/include/dcfg.h index a6f8968..11ef073 100644 --- a/include/dcfg.h +++ b/include/dcfg.h @@ -14,8 +14,8 @@ typedef struct dcfg_Instance dcfg_Instance; // Type definitions typedef struct dcfg_StringView { - char const *data; - size_t size; + char const *data; + size_t size; } dcfg_StringView; typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory. @@ -26,28 +26,28 @@ typedef int (*dcfg_FseekFn)(void *, size_t, int); typedef long (*dcfg_FtellFn)(void *); typedef struct dcfg_InstanceCreateInfo { - // Default using libc - dcfg_AllocFn alloc; - dcfg_FreeFn free; + // Default using libc + dcfg_AllocFn alloc; + dcfg_FreeFn free; - // If POSIX support is enabled, all of those are defined if NULL. - dcfg_RealpathFn realpath; - dcfg_FopenFn fopen; - dcfg_FseekFn fseek; - dcfg_FtellFn ftell; + // If POSIX support is enabled, all of those are defined if NULL. + dcfg_RealpathFn realpath; + dcfg_FopenFn fopen; + dcfg_FseekFn fseek; + dcfg_FtellFn ftell; } dcfg_InstanceCreateInfo; typedef enum dcfg_ValueKind { - dcfg_ValueType_Nil, - dcfg_ValueType_Boolean, - dcfg_ValueType_Integer, - dcfg_ValueType_Real, - dcfg_ValueType_String, - dcfg_ValueType_Path, - dcfg_ValueType_Object, - dcfg_ValueType_Array, - dcfg_ValueType_Function, - dcfg_ValueType_FunctionCall, + dcfg_ValueType_Nil, + dcfg_ValueType_Boolean, + dcfg_ValueType_Integer, + dcfg_ValueType_Real, + dcfg_ValueType_String, + dcfg_ValueType_Path, + dcfg_ValueType_Object, + dcfg_ValueType_Array, + dcfg_ValueType_Function, + dcfg_ValueType_FunctionCall, } dcfg_ValueType; dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info); @@ -57,25 +57,24 @@ char const *dcfg_last_error(dcfg_Instance *instance); // File path gets copied internally to instance to a Value * -> path hashmap for // evaluation. -dcfg_Value *dcfg_parse(dcfg_Instance *instance, - dcfg_StringView const file_path); +dcfg_Value *dcfg_parse( + dcfg_Instance *instance, dcfg_StringView const file_path); void dcfg_destroy(dcfg_Value *value); bool dcfg_serialize_value(dcfg_Value *value, dcfg_StringView *out_sv); // Value type checking dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate); -static inline dcfg_ValueType dcfg_Value_type(dcfg_Value *value) { - return dcfg_Value_type_ex(value, true); +static inline dcfg_ValueType dcfg_Value_type(dcfg_Value *value) +{ + return dcfg_Value_type_ex(value, true); } // Value getters bool dcfg_Value_get_object_field_ex(dcfg_Value *value, - dcfg_StringView const key, - dcfg_Value **out_value, - bool const evaluate); + dcfg_StringView const key, dcfg_Value **out_value, bool const evaluate); bool dcfg_Value_get_array_item_ex(dcfg_Value *value, size_t const index, - dcfg_Value **out_value, bool const evaluate); + dcfg_Value **out_value, bool const evaluate); bool dcfg_Value_get_boolean(dcfg_Value *value, bool *out_value); bool dcfg_Value_get_integer(dcfg_Value *value, int64_t *out_value); @@ -83,22 +82,22 @@ bool dcfg_Value_get_real(dcfg_Value *value, double *out_value); bool dcfg_Value_get_string(dcfg_Value *value, dcfg_StringView *out_sv); bool dcfg_Value_get_path(dcfg_Value *value, dcfg_StringView *out_sv); bool dcfg_Value_get_object_keys(dcfg_Value *value, size_t const capacity, - size_t *out_count, dcfg_StringView *out_keys); + size_t *out_count, dcfg_StringView *out_keys); bool dcfg_Value_get_array_size(dcfg_Value *value, size_t *out_size); -static inline bool dcfg_Value_get_object_field(dcfg_Value *value, - dcfg_StringView const key, - dcfg_Value **out_value) { - return dcfg_Value_get_object_field_ex(value, key, out_value, true); +static inline bool dcfg_Value_get_object_field( + dcfg_Value *value, dcfg_StringView const key, dcfg_Value **out_value) +{ + return dcfg_Value_get_object_field_ex(value, key, out_value, true); } -static inline bool dcfg_Value_get_array_item(dcfg_Value *value, - size_t const index, - dcfg_Value **out_value) { - return dcfg_Value_get_array_item_ex(value, index, out_value, true); +static inline bool dcfg_Value_get_array_item( + dcfg_Value *value, size_t const index, dcfg_Value **out_value) +{ + return dcfg_Value_get_array_item_ex(value, index, out_value, true); } bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args, - size_t arg_count, dcfg_Value **out_value); + size_t arg_count, dcfg_Value **out_value); bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value); #ifdef __cplusplus diff --git a/src/dcfg.c b/src/dcfg.c index f267df9..78bc0cd 100644 --- a/src/dcfg.c +++ b/src/dcfg.c @@ -5,13 +5,13 @@ #include "vendor/vec.h" #ifdef DCFG_POSIX_SUPPORT -#ifdef __sun +# ifdef __sun // FIXME: Fix this stupid shit! -#error "realpath() is dumb and stupid on sun. sorry not sorry." -#endif -#define _XOPEN_SOURCE 200809L +# error "realpath() is dumb and stupid on sun. sorry not sorry." +# endif +# define _XOPEN_SOURCE 200809L #else -#define _POSIX_C_SOURCE 0L +# define _POSIX_C_SOURCE 0L #endif #include @@ -21,10 +21,10 @@ #include #ifdef DCFG_PTHREAD_SUPPORT -#include +# include #else typedef struct { - int unused; + int unused; } pthread_mutex_t; void pthread_mutex_init(pthread_mutex_t *, void *); @@ -33,158 +33,161 @@ void pthread_mutex_lock(pthread_mutex_t *); void pthread_mutex_unlock(pthread_mutex_t *); #endif -int64_t dcfg_strtoll(const char *s, char **end, int base) { - size_t n = strlen(s); - char *clean = malloc(n + 1); - if (!clean) { - errno = ENOMEM; - if (end) - *end = (char *)s; - return 0; - } +int64_t dcfg_strtoll(const char *s, char **end, int base) +{ + size_t n = strlen(s); + char *clean = malloc(n + 1); + if (!clean) { + errno = ENOMEM; + if (end) + *end = (char *)s; + return 0; + } - size_t w = 0; - for (size_t r = 0; r < n && s[r]; ++r) - if (s[r] != '_') - clean[w++] = s[r]; - clean[w] = '\0'; + size_t w = 0; + for (size_t r = 0; r < n && s[r]; ++r) + if (s[r] != '_') + clean[w++] = s[r]; + clean[w] = '\0'; - char *tmp_end; - int64_t v = strtoll(clean, &tmp_end, base); + char *tmp_end; + int64_t v = strtoll(clean, &tmp_end, base); - if (end) { - size_t consumed = (size_t)(tmp_end - clean); - size_t i = 0, c = 0; - while (i < n && c < consumed) { - if (s[i] != '_') - ++c; - ++i; - } - *end = (char *)s + i; - } - free(clean); - return v; + if (end) { + size_t consumed = (size_t)(tmp_end - clean); + size_t i = 0, c = 0; + while (i < n && c < consumed) { + if (s[i] != '_') + ++c; + ++i; + } + *end = (char *)s + i; + } + free(clean); + return v; } -double dcfg_strtod(const char *s, char **end) { - size_t n = strlen(s); - char *clean = malloc(n + 1); - if (!clean) { - errno = ENOMEM; - if (end) - *end = (char *)s; - return 0.0; - } +double dcfg_strtod(char const *s, char **end) +{ + size_t n = strlen(s); + char *clean = malloc(n + 1); + if (!clean) { + errno = ENOMEM; + if (end) + *end = (char *)s; + return 0.0; + } - size_t w = 0; - for (size_t r = 0; r < n && s[r]; ++r) - if (s[r] != '_') - clean[w++] = s[r]; - clean[w] = '\0'; + size_t w = 0; + for (size_t r = 0; r < n && s[r]; ++r) + if (s[r] != '_') + clean[w++] = s[r]; + clean[w] = '\0'; - char *tmp_end; - double v = strtod(clean, &tmp_end); + char *tmp_end; + double v = strtod(clean, &tmp_end); - if (end) { - size_t consumed = (size_t)(tmp_end - clean); - size_t i = 0, c = 0; - while (i < n && c < consumed) { - if (s[i] != '_') - ++c; - ++i; - } - *end = (char *)s + i; - } - free(clean); - return v; + if (end) { + size_t consumed = (size_t)(tmp_end - clean); + size_t i = 0, c = 0; + while (i < n && c < consumed) { + if (s[i] != '_') + ++c; + ++i; + } + *end = (char *)s + i; + } + free(clean); + return v; } typedef dcfg_Value Value; typedef dcfg_Instance Instance; typedef dcfg_StringView StringView; -#define SV(cstr) ((StringView){.data = cstr, .size = strlen(cstr)}) +#define SV(cstr) ((StringView) { .data = cstr, .size = strlen(cstr) }) -static inline bool sv_eq(StringView a, StringView b) { - if (a.size != b.size) { - return false; - } - return memcmp(a.data, b.data, a.size) == 0; +static inline bool sv_eq(StringView a, StringView b) +{ + if (a.size != b.size) { + return false; + } + return memcmp(a.data, b.data, a.size) == 0; } typedef struct { - int row, col; + int row, col; } Location; typedef struct { - Location begin, end; + Location begin, end; } LocationRange; typedef struct { - StringView fp; - LocationRange range; + StringView fp; + LocationRange range; } SourceLocation; typedef struct { - StringView k; - Value *v; + StringView k; + Value *v; } ValueObjectEntry; typedef struct { - ValueObjectEntry *entryv; + ValueObjectEntry *entryv; } ValueObject; typedef struct { - Value **valuev; + Value **valuev; } ValueArray; typedef struct { - StringView *argv; - Value *body; + StringView *argv; + Value *body; } ValueFunctionF; typedef struct { - bool is_builtin; - union { - Value *(*bi)(Value **argv, size_t argc); - ValueFunctionF f; - } v; + bool is_builtin; + union { + Value *(*bi)(Value **argv, size_t argc); + ValueFunctionF f; + } v; } ValueFunction; typedef struct { - Value *function; - Value **argv; + Value *function; + Value **argv; } ValueFunctionCall; struct dcfg_Value { - Instance *instance; - dcfg_ValueType type; - SourceLocation location; + Instance *instance; + dcfg_ValueType type; + SourceLocation location; - union { - int64_t i; - double r; - bool b; - StringView s; - StringView p; - ValueObject o; - ValueArray a; - ValueFunction f; - ValueFunctionCall c; - } v; + union { + int64_t i; + double r; + bool b; + StringView s; + StringView p; + ValueObject o; + ValueArray a; + ValueFunction f; + ValueFunctionCall c; + } v; }; struct dcfg_Instance { - pthread_mutex_t mtx; + pthread_mutex_t mtx; - dcfg_AllocFn alloc; - dcfg_FreeFn free; - dcfg_RealpathFn realpath; - dcfg_FopenFn fopen; - dcfg_FseekFn fseek; - dcfg_FtellFn ftell; + dcfg_AllocFn alloc; + dcfg_FreeFn free; + dcfg_RealpathFn realpath; + dcfg_FopenFn fopen; + dcfg_FseekFn fseek; + dcfg_FtellFn ftell; - char last_error[256]; + char last_error[256]; }; #define ALLOC(sz) (instance->alloc((sz))) @@ -199,150 +202,158 @@ int fseek_(void *f, size_t p, int o) { return fseek(f, p, o); } long ftell_(void *f) { return ftell(f); } #endif -dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) { - assert(create_info); +dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) +{ + assert(create_info); - dcfg_Instance *instance = calloc(1, sizeof(*instance)); - if (!instance) { - return NULL; - } - pthread_mutex_init(&instance->mtx, NULL); + dcfg_Instance *instance = calloc(1, sizeof(*instance)); + if (!instance) { + return NULL; + } + pthread_mutex_init(&instance->mtx, NULL); - instance->alloc = create_info->alloc; - instance->free = create_info->free; - if (!instance->alloc) { - instance->alloc = alloc; - } - if (!instance->free) { - instance->free = free; - } + instance->alloc = create_info->alloc; + instance->free = create_info->free; + if (!instance->alloc) { + instance->alloc = alloc; + } + if (!instance->free) { + instance->free = free; + } #ifdef DCFG_POSIX_SUPPORT - if (!instance->realpath) { - instance->realpath = realpath_; - } - if (!instance->fopen) { - instance->fopen = fopen_; - } - if (!instance->fseek) { - instance->fseek = fseek_; - } - if (!instance->ftell) { - instance->ftell = ftell_; - } + if (!instance->realpath) { + instance->realpath = realpath_; + } + if (!instance->fopen) { + instance->fopen = fopen_; + } + if (!instance->fseek) { + instance->fseek = fseek_; + } + if (!instance->ftell) { + instance->ftell = ftell_; + } #endif - assert(instance->alloc); - assert(instance->free); - assert(instance->realpath); - assert(instance->fopen); - assert(instance->fseek); - assert(instance->ftell); + assert(instance->alloc); + assert(instance->free); + assert(instance->realpath); + assert(instance->fopen); + assert(instance->fseek); + assert(instance->ftell); - return instance; + return instance; } -void dcfg_destroy_instance(dcfg_Instance *instance) { - assert(instance); +void dcfg_destroy_instance(dcfg_Instance *instance) +{ + assert(instance); - pthread_mutex_lock(&instance->mtx); - { // De-init other instance things - } - pthread_mutex_unlock(&instance->mtx); + pthread_mutex_lock(&instance->mtx); + { // De-init other instance things + } + pthread_mutex_unlock(&instance->mtx); - pthread_mutex_destroy(&instance->mtx); + pthread_mutex_destroy(&instance->mtx); - free(instance); + free(instance); } -char const *dcfg_last_error(dcfg_Instance *instance) { - assert(instance); +char const *dcfg_last_error(dcfg_Instance *instance) +{ + assert(instance); - char const *ret = NULL; + char const *ret = NULL; - pthread_mutex_lock(&instance->mtx); - { - if (!instance->last_error[0]) { - pthread_mutex_unlock(&instance->mtx); - return NULL; - } - ret = instance->last_error; - } - pthread_mutex_unlock(&instance->mtx); + pthread_mutex_lock(&instance->mtx); + { + if (!instance->last_error[0]) { + pthread_mutex_unlock(&instance->mtx); + return NULL; + } + ret = instance->last_error; + } + pthread_mutex_unlock(&instance->mtx); - return ret; + return ret; } typedef enum { - TokenType_Identifier, - TokenType_Integer, - TokenType_Real, - TokenType_String, - TokenType_Path, - TokenType_LBracket, - TokenType_RBracket, - TokenType_LParen, - TokenType_RParen, - TokenType_LSquirly, - TokenType_RSquirly, - TokenType_Set, - TokenType_Dot, - TokenType_End, - TokenType_Error, + TokenType_Identifier, + TokenType_Integer, + TokenType_Real, + TokenType_String, + TokenType_Path, + TokenType_LBracket, + TokenType_RBracket, + TokenType_LParen, + TokenType_RParen, + TokenType_LSquirly, + TokenType_RSquirly, + TokenType_Set, + TokenType_Dot, + TokenType_End, + TokenType_Error, } TokenType; typedef struct { - TokenType type; - SourceLocation location; + TokenType type; + SourceLocation location; - union { - StringView id; - int64_t i; - double r; - StringView s; - StringView p; - } v; + union { + StringView id; + int64_t i; + double r; + StringView s; + StringView p; + } v; } Token; typedef struct { - StringView source; - StringView fp; + StringView source; + StringView fp; - int32_t ch, next; - int ch_len, next_len; + int32_t ch, next; + int ch_len, next_len; - Location cursor; - int offset; + Location cursor; + int offset; } Lexer; -static inline int32_t decode_cp(StringView src, int pos, int *len) { - if (pos >= (int)src.size) { - *len = 0; - return -1; - } - return (int32_t)utf8proc_iterate((const uint8_t *)src.data + pos, - (int)(src.size - pos), len); +static inline int32_t decode_cp(StringView src, int pos, int *len) +{ + if (pos >= (int)src.size) { + *len = 0; + return -1; + } + return (int32_t)utf8proc_iterate( + (uint8_t const *)src.data + pos, (int)(src.size - pos), len); } -static inline bool is_space_cp(int32_t cp) { - return (cp <= 0x7F && - (cp == ' ' || cp == '\t' || cp == '\r' || cp == '\n')) || - utf8proc_category(cp) == UTF8PROC_CATEGORY_ZS; +static inline bool is_space_cp(int32_t cp) +{ + return (cp <= 0x7F && (cp == ' ' || cp == '\t' || cp == '\r' || cp == '\n')) + || utf8proc_category(cp) == UTF8PROC_CATEGORY_ZS; } -static inline bool is_alpha_cp(int32_t cp) { - return (cp <= 0x7F && isalpha(cp)) || - (utf8proc_category(cp) >= UTF8PROC_CATEGORY_LU && - utf8proc_category(cp) <= UTF8PROC_CATEGORY_LO); +static inline bool is_alpha_cp(int32_t cp) +{ + return (cp <= 0x7F && isalpha(cp)) + || (utf8proc_category(cp) >= UTF8PROC_CATEGORY_LU + && utf8proc_category(cp) <= UTF8PROC_CATEGORY_LO); } -static inline bool is_digit_cp(int32_t cp) { - return (cp <= 0x7F && isdigit(cp)) || - utf8proc_category(cp) == UTF8PROC_CATEGORY_ND; +static inline bool is_digit_cp(int32_t cp) +{ + return (cp <= 0x7F && isdigit(cp)) + || utf8proc_category(cp) == UTF8PROC_CATEGORY_ND; } -static inline bool is_alnum_cp(int32_t cp) { - return is_alpha_cp(cp) || is_digit_cp(cp); +static inline bool is_alnum_cp(int32_t cp) +{ + return is_alpha_cp(cp) || is_digit_cp(cp); } -static inline bool is_path_ch_cp(int32_t cp) { - return cp == '_' || cp == '.' || cp == '/' || cp == '-' || cp == ':' || - is_alnum_cp(cp); +static inline bool is_path_ch_cp(int32_t cp) +{ + return cp == '_' || cp == '.' || cp == '/' || cp == '-' || cp == ':' + || is_alnum_cp(cp); } #define is_space is_space_cp @@ -351,300 +362,312 @@ static inline bool is_path_ch_cp(int32_t cp) { #define isdigit_cp is_digit_cp #define isalnum_cp is_alnum_cp -static void lex_advance(Lexer *lx) { - if (lx->next == -1) { - lx->ch = -1; - return; - } - if (lx->ch == '\n') { - ++lx->cursor.row; - lx->cursor.col = 1; - } else { - ++lx->cursor.col; - } +static void lex_advance(Lexer *lx) +{ + if (lx->next == -1) { + lx->ch = -1; + return; + } + if (lx->ch == '\n') { + ++lx->cursor.row; + lx->cursor.col = 1; + } else { + ++lx->cursor.col; + } - lx->offset += lx->ch_len; - lx->ch = lx->next; - lx->ch_len = lx->next_len; + lx->offset += lx->ch_len; + lx->ch = lx->next; + lx->ch_len = lx->next_len; - lx->next = decode_cp(lx->source, lx->offset + lx->ch_len, &lx->next_len); + lx->next = decode_cp(lx->source, lx->offset + lx->ch_len, &lx->next_len); } -static StringView lex_slice(Lexer *lx, int start, int end) { - StringView sv; - sv.data = lx->source.data + start; - sv.size = (size_t)(end - start); - return sv; +static StringView lex_slice(Lexer *lx, int start, int end) +{ + StringView sv; + sv.data = lx->source.data + start; + sv.size = (size_t)(end - start); + return sv; } -static void skip_ws_and_comments(Lexer *lx) { - for (;;) { - while (is_space(lx->ch)) - lex_advance(lx); - if (lx->ch == '#') { - while (lx->ch != -1 && lx->ch != '\n') - lex_advance(lx); - continue; - } - break; - } +static void skip_ws_and_comments(Lexer *lx) +{ + for (;;) { + while (is_space(lx->ch)) + lex_advance(lx); + if (lx->ch == '#') { + while (lx->ch != -1 && lx->ch != '\n') + lex_advance(lx); + continue; + } + break; + } } -static Token make_token(TokenType t, Lexer *lx, int start, int end) { - Token tk = {0}; - tk.type = t; - tk.location.fp = lx->fp; - tk.location.range.begin = lx->cursor; - tk.location.range.end = lx->cursor; +static Token make_token(TokenType t, Lexer *lx, int start, int end) +{ + Token tk = { 0 }; + tk.type = t; + tk.location.fp = lx->fp; + tk.location.range.begin = lx->cursor; + tk.location.range.end = lx->cursor; - switch (t) { - case TokenType_Identifier: - tk.v.id = lex_slice(lx, start, end); - break; - case TokenType_Integer: - tk.v.i = dcfg_strtoll(lex_slice(lx, start, end).data, NULL, 10); - break; - case TokenType_Real: - tk.v.r = dcfg_strtod(lex_slice(lx, start, end).data, NULL); - break; - case TokenType_String: - tk.v.s = lex_slice(lx, start, end); - break; - case TokenType_Path: - tk.v.p = lex_slice(lx, start, end); - break; - default: - break; - } - return tk; + switch (t) { + case TokenType_Identifier: + tk.v.id = lex_slice(lx, start, end); + break; + case TokenType_Integer: + tk.v.i = dcfg_strtoll(lex_slice(lx, start, end).data, NULL, 10); + break; + case TokenType_Real: + tk.v.r = dcfg_strtod(lex_slice(lx, start, end).data, NULL); + break; + case TokenType_String: + tk.v.s = lex_slice(lx, start, end); + break; + case TokenType_Path: + tk.v.p = lex_slice(lx, start, end); + break; + default: + break; + } + return tk; } -static Token lex_number(Lexer *lx) { - int start = lx->offset; - bool real = false; +static Token lex_number(Lexer *lx) +{ + int start = lx->offset; + bool real = false; - while (isdigit_cp(lx->ch) || lx->ch == '_') - lex_advance(lx); - if (lx->ch == '.') { - real = true; - lex_advance(lx); - while (isdigit_cp(lx->ch) || lx->ch == '_') - lex_advance(lx); - } - return make_token(real ? TokenType_Real : TokenType_Integer, lx, start, - lx->offset); + while (isdigit_cp(lx->ch) || lx->ch == '_') + lex_advance(lx); + if (lx->ch == '.') { + real = true; + lex_advance(lx); + while (isdigit_cp(lx->ch) || lx->ch == '_') + lex_advance(lx); + } + return make_token( + real ? TokenType_Real : TokenType_Integer, lx, start, lx->offset); } -static Token lex_identifier(Lexer *lx) { - int start = lx->offset; - while (isalnum_cp(lx->ch) || lx->ch == '_') - lex_advance(lx); - return make_token(TokenType_Identifier, lx, start, lx->offset); +static Token lex_identifier(Lexer *lx) +{ + int start = lx->offset; + while (isalnum_cp(lx->ch) || lx->ch == '_') + lex_advance(lx); + return make_token(TokenType_Identifier, lx, start, lx->offset); } -static Token lex_string(Lexer *lx) { - int quote = lx->ch; - lex_advance(lx); // skip opening quote - int start = lx->offset; - while (lx->ch != quote && lx->ch != -1) { - if (lx->ch == '\\' && lx->next != -1) - lex_advance(lx); // simple escapes - lex_advance(lx); - } - int end = lx->offset; - if (lx->ch == quote) - lex_advance(lx); // skip closing quote - return make_token(TokenType_String, lx, start, end); +static Token lex_string(Lexer *lx) +{ + int quote = lx->ch; + lex_advance(lx); // skip opening quote + int start = lx->offset; + while (lx->ch != quote && lx->ch != -1) { + if (lx->ch == '\\' && lx->next != -1) + lex_advance(lx); // simple escapes + lex_advance(lx); + } + int end = lx->offset; + if (lx->ch == quote) + lex_advance(lx); // skip closing quote + return make_token(TokenType_String, lx, start, end); } -static Token lex_path(Lexer *lx) { - int start = lx->offset; - for (;;) { - if (lx->ch == '\\') { - lex_advance(lx); - if (lx->ch != -1) - lex_advance(lx); - } else if (is_path_ch(lx->ch)) { - lex_advance(lx); - } else - break; - } - return make_token(TokenType_Path, lx, start, lx->offset); +static Token lex_path(Lexer *lx) +{ + int start = lx->offset; + for (;;) { + if (lx->ch == '\\') { + lex_advance(lx); + if (lx->ch != -1) + lex_advance(lx); + } else if (is_path_ch(lx->ch)) { + lex_advance(lx); + } else + break; + } + return make_token(TokenType_Path, lx, start, lx->offset); } -bool Lexer_init(Lexer *lx, StringView src, StringView fp) { - memset(lx, 0, sizeof *lx); - lx->source = src; - lx->fp = fp; - lx->cursor = (Location){1, 1}; +bool Lexer_init(Lexer *lx, StringView src, StringView fp) +{ + memset(lx, 0, sizeof *lx); + lx->source = src; + lx->fp = fp; + lx->cursor = (Location) { 1, 1 }; - lx->ch = decode_cp(src, 0, &lx->ch_len); - lx->next = decode_cp(src, lx->ch_len, &lx->next_len); - return true; + lx->ch = decode_cp(src, 0, &lx->ch_len); + lx->next = decode_cp(src, lx->ch_len, &lx->next_len); + return true; } -Token Lexer_next(Lexer *lx) { - skip_ws_and_comments(lx); - int start_off = lx->offset; +Token Lexer_next(Lexer *lx) +{ + skip_ws_and_comments(lx); + int start_off = lx->offset; - if (lx->ch == -1) { - Token tk = {.type = TokenType_End}; - tk.location.fp = lx->fp; - return tk; - } + if (lx->ch == -1) { + Token tk = { .type = TokenType_End }; + tk.location.fp = lx->fp; + return tk; + } - if (lx->ch == '/' // "/foo" - || (lx->ch == '.' && lx->next == '/') // "./foo" - || (lx->ch == '.' && lx->offset + 2 < (int)lx->source.size && - lx->source.data[lx->offset + 1] == '.' && - lx->source.data[lx->offset + 2] == '/') // "../foo" - || (isalpha_cp(lx->ch) && lx->next == ':')) { // "C:/foo" - return lex_path(lx); - } + if (lx->ch == '/' // "/foo" + || (lx->ch == '.' && lx->next == '/') // "./foo" + || (lx->ch == '.' && lx->offset + 2 < (int)lx->source.size + && lx->source.data[lx->offset + 1] == '.' + && lx->source.data[lx->offset + 2] == '/') // "../foo" + || (isalpha_cp(lx->ch) && lx->next == ':')) { // "C:/foo" + return lex_path(lx); + } - switch (lx->ch) { - case '[': - lex_advance(lx); - return make_token(TokenType_LBracket, lx, start_off, lx->offset); - case ']': - lex_advance(lx); - return make_token(TokenType_RBracket, lx, start_off, lx->offset); - case '(': - lex_advance(lx); - return make_token(TokenType_LParen, lx, start_off, lx->offset); - case ')': - lex_advance(lx); - return make_token(TokenType_RParen, lx, start_off, lx->offset); - case '{': - lex_advance(lx); - return make_token(TokenType_LSquirly, lx, start_off, lx->offset); - case '}': - lex_advance(lx); - return make_token(TokenType_RSquirly, lx, start_off, lx->offset); - case '=': - lex_advance(lx); - return make_token(TokenType_Set, lx, start_off, lx->offset); - case '.': - lex_advance(lx); - return make_token(TokenType_Dot, lx, start_off, lx->offset); - case '"': - case '\'': - return lex_string(lx); - default: - break; - } + switch (lx->ch) { + case '[': + lex_advance(lx); + return make_token(TokenType_LBracket, lx, start_off, lx->offset); + case ']': + lex_advance(lx); + return make_token(TokenType_RBracket, lx, start_off, lx->offset); + case '(': + lex_advance(lx); + return make_token(TokenType_LParen, lx, start_off, lx->offset); + case ')': + lex_advance(lx); + return make_token(TokenType_RParen, lx, start_off, lx->offset); + case '{': + lex_advance(lx); + return make_token(TokenType_LSquirly, lx, start_off, lx->offset); + case '}': + lex_advance(lx); + return make_token(TokenType_RSquirly, lx, start_off, lx->offset); + case '=': + lex_advance(lx); + return make_token(TokenType_Set, lx, start_off, lx->offset); + case '.': + lex_advance(lx); + return make_token(TokenType_Dot, lx, start_off, lx->offset); + case '"': + case '\'': + return lex_string(lx); + default: + break; + } - if (isalpha_cp(lx->ch) || lx->ch == '_') - return lex_identifier(lx); - if (isdigit_cp(lx->ch)) - return lex_number(lx); + if (isalpha_cp(lx->ch) || lx->ch == '_') + return lex_identifier(lx); + if (isdigit_cp(lx->ch)) + return lex_number(lx); - Token err = {.type = TokenType_Error}; - err.location.fp = lx->fp; - lex_advance(lx); - return err; + Token err = { .type = TokenType_Error }; + err.location.fp = lx->fp; + lex_advance(lx); + return err; } typedef enum { - ASTKind_Key, // Identifier + string combo - ASTKind_Path, - ASTKind_Boolean, - ASTKind_Integer, - ASTKind_Real, - ASTKind_Block, - ASTKind_Array, - ASTKind_Function, - ASTKind_MemberAccess, - ASTKind_FunctionCall, + ASTKind_Key, // Identifier + string combo + ASTKind_Path, + ASTKind_Boolean, + ASTKind_Integer, + ASTKind_Real, + ASTKind_Block, + ASTKind_Array, + ASTKind_Function, + ASTKind_MemberAccess, + ASTKind_FunctionCall, } ASTKind; typedef struct AST AST; typedef struct { - StringView *argv; - AST *body; + StringView *argv; + AST *body; } ASTFunction; typedef struct { - AST **childv; + AST **childv; } ASTArray; typedef struct { - AST *k; // Either MemberAccess or Key - AST *v; + AST *k; // Either MemberAccess or Key + AST *v; } ASTBlock_Entry; typedef struct { - ASTBlock_Entry *entryv; + ASTBlock_Entry *entryv; } ASTBlock; typedef struct { - StringView *accessv; + StringView *accessv; } ASTMemberAccess; typedef struct { - AST *function; - AST **argv; + AST *function; + AST **argv; } ASTFunctionCall; struct AST { - ASTKind kind; - SourceLocation location; - union { - int64_t i; - double r; - StringView s; - StringView p; - bool b; - ASTFunction f; - ASTArray a; - ASTBlock bl; - ASTMemberAccess m; - ASTFunctionCall fc; - } v; + ASTKind kind; + SourceLocation location; + union { + int64_t i; + double r; + StringView s; + StringView p; + bool b; + ASTFunction f; + ASTArray a; + ASTBlock bl; + ASTMemberAccess m; + ASTFunctionCall fc; + } v; }; typedef struct { - Lexer *lexer; - Instance *instance; + Lexer *lexer; + Instance *instance; - Token cur, next; + Token cur, next; } Parser; -bool Parser_next(Parser *parser) { - parser->cur = parser->next; - parser->next = Lexer_next(parser->lexer); - bool ret = parser->next.type != TokenType_Error; - if (!ret) { - strcpy(parser->instance->last_error, "Failed to get parser token"); - } - return ret; +bool Parser_next(Parser *parser) +{ + parser->cur = parser->next; + parser->next = Lexer_next(parser->lexer); + bool ret = parser->next.type != TokenType_Error; + if (!ret) { + strcpy(parser->instance->last_error, "Failed to get parser token"); + } + return ret; } -bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance) { - out_parser->lexer = lexer; - out_parser->instance = instance; - if (!Parser_next(out_parser)) { - return false; - } - if (!Parser_next(out_parser)) { - return false; - } - return true; +bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance) +{ + out_parser->lexer = lexer; + out_parser->instance = instance; + if (!Parser_next(out_parser)) { + return false; + } + if (!Parser_next(out_parser)) { + return false; + } + return true; } -bool Parser_accept(Parser *parser, TokenType type, - SourceLocation *out_location) { - if (parser->cur.type == type) { - if (out_location) { - *out_location = parser->cur.location; - } - if (!Parser_next(parser)) { - return false; - } - return true; - } - return false; +bool Parser_accept(Parser *parser, TokenType type, SourceLocation *out_location) +{ + if (parser->cur.type == type) { + if (out_location) { + *out_location = parser->cur.location; + } + if (!Parser_next(parser)) { + return false; + } + return true; + } + return false; } #undef ALLOC @@ -652,289 +675,299 @@ bool Parser_accept(Parser *parser, TokenType type, #define ALLOC(sz) (parser->instance->alloc((sz))) #define FREE(ptr) (parser->instance->free((ptr))) -void AST_free_parser(AST *ast, Parser *parser) { - assert(parser); - if (!ast) { - return; - } +void AST_free_parser(AST *ast, Parser *parser) +{ + assert(parser); + if (!ast) { + return; + } - switch (ast->kind) { - case ASTKind_Function: - AST_free_parser(ast->v.f.body, parser); - vector_free(ast->v.f.argv); - break; - case ASTKind_Array: - for (size_t i = 0; i < vector_size(ast->v.a.childv); i++) - AST_free_parser(ast->v.a.childv[i], parser); - vector_free(ast->v.a.childv); - break; - case ASTKind_Block: - for (size_t i = 0; i < vector_size(ast->v.bl.entryv); i++) { - AST_free_parser(ast->v.bl.entryv[i].k, parser); - AST_free_parser(ast->v.bl.entryv[i].v, parser); - } - vector_free(ast->v.bl.entryv); - break; - case ASTKind_MemberAccess: - vector_free(ast->v.m.accessv); - break; - case ASTKind_FunctionCall: - AST_free_parser(ast->v.fc.function, parser); - for (size_t i = 0; i < vector_size(ast->v.fc.argv); i++) - AST_free_parser(ast->v.fc.argv[i], parser); - vector_free(ast->v.fc.argv); - break; - default: - break; - } + switch (ast->kind) { + case ASTKind_Function: + AST_free_parser(ast->v.f.body, parser); + vector_free(ast->v.f.argv); + break; + case ASTKind_Array: + for (size_t i = 0; i < vector_size(ast->v.a.childv); i++) + AST_free_parser(ast->v.a.childv[i], parser); + vector_free(ast->v.a.childv); + break; + case ASTKind_Block: + for (size_t i = 0; i < vector_size(ast->v.bl.entryv); i++) { + AST_free_parser(ast->v.bl.entryv[i].k, parser); + AST_free_parser(ast->v.bl.entryv[i].v, parser); + } + vector_free(ast->v.bl.entryv); + break; + case ASTKind_MemberAccess: + vector_free(ast->v.m.accessv); + break; + case ASTKind_FunctionCall: + AST_free_parser(ast->v.fc.function, parser); + for (size_t i = 0; i < vector_size(ast->v.fc.argv); i++) + AST_free_parser(ast->v.fc.argv[i], parser); + vector_free(ast->v.fc.argv); + break; + default: + break; + } - FREE(ast); + FREE(ast); } -AST *parser_parse_dot_access(Parser *parser, StringView *current) { - assert(parser); - assert(parser->cur.type == TokenType_Identifier || - parser->cur.type == TokenType_String); +AST *parser_parse_dot_access(Parser *parser, StringView *current) +{ + assert(parser); + assert(parser->cur.type == TokenType_Identifier + || parser->cur.type == TokenType_String); - StringView *accessv = vector_create(); - if (!accessv) { - strcpy(parser->instance->last_error, "Failed to allocate vector"); - return NULL; - } - if (current) { - vector_add(&accessv, *current); - } + StringView *accessv = vector_create(); + if (!accessv) { + strcpy(parser->instance->last_error, "Failed to allocate vector"); + return NULL; + } + if (current) { + vector_add(&accessv, *current); + } - SourceLocation loc = parser->cur.location; - SourceLocation last_loc = parser->cur.location; - while (true) { - if (parser->cur.type != TokenType_Identifier && - parser->cur.type != TokenType_String) { - break; - } + SourceLocation loc = parser->cur.location; + SourceLocation last_loc = parser->cur.location; + while (true) { + if (parser->cur.type != TokenType_Identifier + && parser->cur.type != TokenType_String) { + break; + } - last_loc = parser->cur.location; - vector_add(&accessv, parser->cur.v.s); + last_loc = parser->cur.location; + vector_add(&accessv, parser->cur.v.s); - if (!Parser_next(parser)) { - strcpy(parser->instance->last_error, - "Failed to get next token in dot access parsing"); - vector_free(accessv); - return NULL; - } + if (!Parser_next(parser)) { + strcpy(parser->instance->last_error, + "Failed to get next token in dot access parsing"); + vector_free(accessv); + return NULL; + } - if (!Parser_accept(parser, TokenType_Dot, NULL)) { - break; - } - } + if (!Parser_accept(parser, TokenType_Dot, NULL)) { + break; + } + } - assert(vector_size(accessv) != 0); + assert(vector_size(accessv) != 0); - loc.range.end = last_loc.range.end; + loc.range.end = last_loc.range.end; - AST *ast = ALLOC(sizeof(*ast)); - ast->kind = ASTKind_MemberAccess; - ast->v.m.accessv = accessv; - ast->location = loc; + AST *ast = ALLOC(sizeof(*ast)); + ast->kind = ASTKind_MemberAccess; + ast->v.m.accessv = accessv; + ast->location = loc; - if (vector_size(accessv) == 1) { - ast->kind = ASTKind_Key; - ast->v.s = accessv[0]; - vector_free(accessv); - } - return ast; + if (vector_size(accessv) == 1) { + ast->kind = ASTKind_Key; + ast->v.s = accessv[0]; + vector_free(accessv); + } + return ast; } -AST *parser_parse_value(Parser *parser) { - AST *ast = ALLOC(sizeof(*ast)); - ast->location = parser->cur.location; - if (parser->cur.type == TokenType_Integer) { - ast->kind = ASTKind_Integer; - ast->v.i = parser->cur.v.i; - } else if (parser->cur.type == TokenType_Real) { - ast->kind = ASTKind_Real; - ast->v.r = parser->cur.v.r; - } else if (parser->cur.type == TokenType_String || - parser->cur.type == TokenType_Identifier) { - ast->kind = ASTKind_Key; - ast->v.s = parser->cur.v.s; +AST *parser_parse_value(Parser *parser) +{ + AST *ast = ALLOC(sizeof(*ast)); + ast->location = parser->cur.location; + if (parser->cur.type == TokenType_Integer) { + ast->kind = ASTKind_Integer; + ast->v.i = parser->cur.v.i; + } else if (parser->cur.type == TokenType_Real) { + ast->kind = ASTKind_Real; + ast->v.r = parser->cur.v.r; + } else if (parser->cur.type == TokenType_String + || parser->cur.type == TokenType_Identifier) { + ast->kind = ASTKind_Key; + ast->v.s = parser->cur.v.s; - if (parser->next.type == TokenType_Dot) { - FREE(ast); - return parser_parse_dot_access(parser, NULL); - } else if (parser->cur.type == TokenType_Identifier) { - if (sv_eq(ast->v.s, SV("fn"))) { - if (!Parser_next(parser)) { - strcpy(parser->instance->last_error, "Failed to advance fn keyword"); - FREE(ast); - return NULL; - } + if (parser->next.type == TokenType_Dot) { + FREE(ast); + return parser_parse_dot_access(parser, NULL); + } else if (parser->cur.type == TokenType_Identifier) { + if (sv_eq(ast->v.s, SV("fn"))) { + if (!Parser_next(parser)) { + strcpy(parser->instance->last_error, + "Failed to advance fn keyword"); + FREE(ast); + return NULL; + } - ast->kind = ASTKind_Function; - ast->v.f.argv = vector_create(); - if (!ast->v.f.argv) { - strcpy(parser->instance->last_error, "Failed to allocate vector"); - FREE(ast); - return NULL; - } + ast->kind = ASTKind_Function; + ast->v.f.argv = vector_create(); + if (!ast->v.f.argv) { + strcpy(parser->instance->last_error, + "Failed to allocate vector"); + FREE(ast); + return NULL; + } - while (true) { - if (Parser_accept(parser, TokenType_Set, NULL)) { - break; - } + while (true) { + if (Parser_accept(parser, TokenType_Set, NULL)) { + break; + } - if (parser->cur.type != TokenType_Identifier) { - strcpy(parser->instance->last_error, - "Expected identifier for function argument"); - vector_free(ast->v.f.argv); - FREE(ast); - return NULL; - } + if (parser->cur.type != TokenType_Identifier) { + strcpy(parser->instance->last_error, + "Expected identifier for function argument"); + vector_free(ast->v.f.argv); + FREE(ast); + return NULL; + } - vector_add(&ast->v.f.argv, parser->cur.v.s); - } + vector_add(&ast->v.f.argv, parser->cur.v.s); + } - ast->v.f.body = parser_parse_value(parser); - if (!ast->v.f.body) { - vector_free(ast->v.f.argv); - FREE(ast); - return NULL; - } - ast->location.range.end = ast->v.f.body->location.range.end; - return ast; - } else if (sv_eq(ast->v.s, SV("on")) || sv_eq(ast->v.s, SV("true"))) { - ast->kind = ASTKind_Boolean; - ast->v.b = true; - } else if (sv_eq(ast->v.s, SV("off")) || sv_eq(ast->v.s, SV("false"))) { - ast->kind = ASTKind_Boolean; - ast->v.b = false; - } - } - } else if (parser->cur.type == TokenType_Path) { - ast->kind = ASTKind_Path; - ast->v.p = parser->cur.v.p; - } else if (Parser_accept(parser, TokenType_LBracket, NULL)) { - ast->kind = ASTKind_Array; - ast->v.a.childv = vector_create(); - if (!ast->v.a.childv) { - strcpy(parser->instance->last_error, "Failed to allocate vector"); - FREE(ast); - return NULL; - } - SourceLocation rbracket_loc; - while (true) { - if (Parser_accept(parser, TokenType_RBracket, &rbracket_loc)) { - break; - } + ast->v.f.body = parser_parse_value(parser); + if (!ast->v.f.body) { + vector_free(ast->v.f.argv); + FREE(ast); + return NULL; + } + ast->location.range.end = ast->v.f.body->location.range.end; + return ast; + } else if (sv_eq(ast->v.s, SV("on")) + || sv_eq(ast->v.s, SV("true"))) { + ast->kind = ASTKind_Boolean; + ast->v.b = true; + } else if (sv_eq(ast->v.s, SV("off")) + || sv_eq(ast->v.s, SV("false"))) { + ast->kind = ASTKind_Boolean; + ast->v.b = false; + } + } + } else if (parser->cur.type == TokenType_Path) { + ast->kind = ASTKind_Path; + ast->v.p = parser->cur.v.p; + } else if (Parser_accept(parser, TokenType_LBracket, NULL)) { + ast->kind = ASTKind_Array; + ast->v.a.childv = vector_create(); + if (!ast->v.a.childv) { + strcpy(parser->instance->last_error, "Failed to allocate vector"); + FREE(ast); + return NULL; + } + SourceLocation rbracket_loc; + while (true) { + if (Parser_accept(parser, TokenType_RBracket, &rbracket_loc)) { + break; + } - AST *value = parser_parse_value(parser); - if (!value) { - for (size_t i = 0; i < vector_size(ast->v.a.childv); i++) { - AST_free_parser(ast->v.a.childv[i], parser); - } - vector_free(ast->v.a.childv); - FREE(ast); - return NULL; - } - vector_add(&ast->v.a.childv, value); - } - ast->location.range.end = rbracket_loc.range.end; - return ast; - } else if (Parser_accept(parser, TokenType_LSquirly, NULL)) { - ast->kind = ASTKind_Block; - ast->v.bl.entryv = vector_create(); - if (!ast->v.bl.entryv) { - strcpy(parser->instance->last_error, "Failed to allocate vector"); - FREE(ast); - return NULL; - } - SourceLocation rsquirly_loc; - while (true) { - if (Parser_accept(parser, TokenType_RSquirly, &rsquirly_loc)) { - break; - } + AST *value = parser_parse_value(parser); + if (!value) { + for (size_t i = 0; i < vector_size(ast->v.a.childv); i++) { + AST_free_parser(ast->v.a.childv[i], parser); + } + vector_free(ast->v.a.childv); + FREE(ast); + return NULL; + } + vector_add(&ast->v.a.childv, value); + } + ast->location.range.end = rbracket_loc.range.end; + return ast; + } else if (Parser_accept(parser, TokenType_LSquirly, NULL)) { + ast->kind = ASTKind_Block; + ast->v.bl.entryv = vector_create(); + if (!ast->v.bl.entryv) { + strcpy(parser->instance->last_error, "Failed to allocate vector"); + FREE(ast); + return NULL; + } + SourceLocation rsquirly_loc; + while (true) { + if (Parser_accept(parser, TokenType_RSquirly, &rsquirly_loc)) { + break; + } - if (parser->cur.type != TokenType_Identifier && - parser->cur.type != TokenType_String) { - strcpy(parser->instance->last_error, - "Expected identifier or string for object key"); - vector_free(ast->v.bl.entryv); - FREE(ast); - return NULL; - } + if (parser->cur.type != TokenType_Identifier + && parser->cur.type != TokenType_String) { + strcpy(parser->instance->last_error, + "Expected identifier or string for object key"); + vector_free(ast->v.bl.entryv); + FREE(ast); + return NULL; + } - AST *key = parser_parse_dot_access(parser, NULL); - if (!Parser_accept(parser, TokenType_Set, NULL)) { - strcpy(parser->instance->last_error, "Expected = after object key"); - vector_free(ast->v.bl.entryv); - FREE(ast); - return NULL; - } + AST *key = parser_parse_dot_access(parser, NULL); + if (!Parser_accept(parser, TokenType_Set, NULL)) { + strcpy(parser->instance->last_error, + "Expected = after object key"); + vector_free(ast->v.bl.entryv); + FREE(ast); + return NULL; + } - AST *value = parser_parse_value(parser); - if (!value) { - AST_free_parser(key, parser); - vector_free(ast->v.bl.entryv); - FREE(ast); - return NULL; - } + AST *value = parser_parse_value(parser); + if (!value) { + AST_free_parser(key, parser); + vector_free(ast->v.bl.entryv); + FREE(ast); + return NULL; + } - assert(key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key); - ASTBlock_Entry entry = { - .k = key, - .v = value, - }; - vector_add(&ast->v.bl.entryv, entry); - } - return ast; - } else if (Parser_accept(parser, TokenType_LParen, NULL)) { - ast->kind = ASTKind_FunctionCall; - ast->v.fc.function = parser_parse_value(parser); - ast->v.fc.argv = vector_create(); - if (!ast->v.fc.argv) { - strcpy(parser->instance->last_error, "Failed to allocate vector"); - FREE(ast); - return NULL; - } + assert( + key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key); + ASTBlock_Entry entry = { + .k = key, + .v = value, + }; + vector_add(&ast->v.bl.entryv, entry); + } + return ast; + } else if (Parser_accept(parser, TokenType_LParen, NULL)) { + ast->kind = ASTKind_FunctionCall; + ast->v.fc.function = parser_parse_value(parser); + ast->v.fc.argv = vector_create(); + if (!ast->v.fc.argv) { + strcpy(parser->instance->last_error, "Failed to allocate vector"); + FREE(ast); + return NULL; + } - SourceLocation rparen_loc; - while (true) { - if (Parser_accept(parser, TokenType_RParen, &rparen_loc)) { - break; - } + SourceLocation rparen_loc; + while (true) { + if (Parser_accept(parser, TokenType_RParen, &rparen_loc)) { + break; + } - AST *value = parser_parse_value(parser); - if (!value) { - for (size_t i = 0; i < vector_size(ast->v.fc.argv); i++) { - AST_free_parser(ast->v.fc.argv[i], parser); - } - vector_free(ast->v.fc.argv); - FREE(ast); - return NULL; - } + AST *value = parser_parse_value(parser); + if (!value) { + for (size_t i = 0; i < vector_size(ast->v.fc.argv); i++) { + AST_free_parser(ast->v.fc.argv[i], parser); + } + vector_free(ast->v.fc.argv); + FREE(ast); + return NULL; + } - vector_add(&ast->v.fc.argv, value); - } + vector_add(&ast->v.fc.argv, value); + } - ast->location.range.end = rparen_loc.range.end; + ast->location.range.end = rparen_loc.range.end; - return ast; - } else { - if (parser->cur.type == TokenType_End) { - strcpy(parser->instance->last_error, "Expected value, got end of file"); - } else { - strcpy(parser->instance->last_error, "Unexpected token for value"); - } - FREE(ast); - ast = NULL; - } - if (!Parser_next(parser)) { - if (ast) { - FREE(ast); - } - return NULL; - } - return ast; + return ast; + } else { + if (parser->cur.type == TokenType_End) { + strcpy(parser->instance->last_error, + "Expected value, got end of file"); + } else { + strcpy(parser->instance->last_error, "Unexpected token for value"); + } + FREE(ast); + ast = NULL; + } + if (!Parser_next(parser)) { + if (ast) { + FREE(ast); + } + return NULL; + } + return ast; } // TODO: Print SourceLocation in last error. @@ -945,176 +978,178 @@ AST *Parser_parse(Parser *parser) { return parser_parse_value(parser); } #define ALLOC(sz) (instance->alloc((sz))) #define FREE(ptr) (instance->free((ptr))) -Value *ast_to_value(dcfg_Instance *instance, AST *root) { - Value *value = ALLOC(sizeof(*value)); - value->instance = instance; - if (root->kind == ASTKind_Key) { - // FIXME: Implement - FREE(value); - return NULL; - } else if (root->kind == ASTKind_Path) { - value->type = dcfg_ValueType_Path; - value->v.p = root->v.p; - } else if (root->kind == ASTKind_Boolean) { - value->type = dcfg_ValueType_Boolean; - value->v.b = root->v.b; - } else if (root->kind == ASTKind_Integer) { - value->type = dcfg_ValueType_Integer; - value->v.i = root->v.i; - } else if (root->kind == ASTKind_Real) { - value->type = dcfg_ValueType_Real; - value->v.r = root->v.r; - } else if (root->kind == ASTKind_Block) { - // FIXME: Implement - FREE(value); - return NULL; - } else if (root->kind == ASTKind_Array) { - value->type = dcfg_ValueType_Array; - value->v.a.valuev = vector_create(); - for (size_t i = 0; i < vector_size(root->v.a.childv); i++) { - Value *v = ast_to_value(instance, root->v.a.childv[i]); - if (!v) { - for (size_t i = 0; i < vector_size(value->v.a.valuev); i++) { - dcfg_destroy(value->v.a.valuev[i]); - } - vector_free(value->v.a.valuev); - FREE(value); - return NULL; - } - vector_add(&value->v.a.valuev, v); - } - } else if (root->kind == ASTKind_Function) { - value->type = dcfg_ValueType_Function; - value->v.f.is_builtin = false; - value->v.f.v.f.argv = vector_create(); - for (size_t i = 0; i < vector_size(root->v.f.argv); i++) { - vector_add(&value->v.f.v.f.argv, root->v.f.argv[i]); - } - Value *v = ast_to_value(instance, root->v.f.body); - if (!v) { - vector_free(value->v.f.v.f.argv); - FREE(value); - return NULL; - } - value->v.f.v.f.body = v; - } else if (root->kind == ASTKind_MemberAccess) { - // FIXME: Implement - FREE(value); - return NULL; - } else if (root->kind == ASTKind_FunctionCall) { - value->type = dcfg_ValueType_FunctionCall; - Value *function = ast_to_value(instance, root->v.fc.function); - if (!function) { - FREE(value); - return NULL; - } - value->v.c.function = function; - value->v.c.argv = vector_create(); +Value *ast_to_value(dcfg_Instance *instance, AST *root) +{ + Value *value = ALLOC(sizeof(*value)); + value->instance = instance; + if (root->kind == ASTKind_Key) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_Path) { + value->type = dcfg_ValueType_Path; + value->v.p = root->v.p; + } else if (root->kind == ASTKind_Boolean) { + value->type = dcfg_ValueType_Boolean; + value->v.b = root->v.b; + } else if (root->kind == ASTKind_Integer) { + value->type = dcfg_ValueType_Integer; + value->v.i = root->v.i; + } else if (root->kind == ASTKind_Real) { + value->type = dcfg_ValueType_Real; + value->v.r = root->v.r; + } else if (root->kind == ASTKind_Block) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_Array) { + value->type = dcfg_ValueType_Array; + value->v.a.valuev = vector_create(); + for (size_t i = 0; i < vector_size(root->v.a.childv); i++) { + Value *v = ast_to_value(instance, root->v.a.childv[i]); + if (!v) { + for (size_t i = 0; i < vector_size(value->v.a.valuev); i++) { + dcfg_destroy(value->v.a.valuev[i]); + } + vector_free(value->v.a.valuev); + FREE(value); + return NULL; + } + vector_add(&value->v.a.valuev, v); + } + } else if (root->kind == ASTKind_Function) { + value->type = dcfg_ValueType_Function; + value->v.f.is_builtin = false; + value->v.f.v.f.argv = vector_create(); + for (size_t i = 0; i < vector_size(root->v.f.argv); i++) { + vector_add(&value->v.f.v.f.argv, root->v.f.argv[i]); + } + Value *v = ast_to_value(instance, root->v.f.body); + if (!v) { + vector_free(value->v.f.v.f.argv); + FREE(value); + return NULL; + } + value->v.f.v.f.body = v; + } else if (root->kind == ASTKind_MemberAccess) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_FunctionCall) { + value->type = dcfg_ValueType_FunctionCall; + Value *function = ast_to_value(instance, root->v.fc.function); + if (!function) { + FREE(value); + return NULL; + } + value->v.c.function = function; + value->v.c.argv = vector_create(); - for (size_t i = 0; i < vector_size(root->v.fc.argv); i++) { - Value *arg = ast_to_value(instance, root->v.fc.argv[i]); - if (!arg) { - // TODO: Free argv values - for (size_t i = 0; i < vector_size(value->v.c.argv); i++) { - dcfg_destroy(value->v.c.argv[i]); - } - vector_free(value->v.c.argv); - FREE(value); - return NULL; - } - vector_add(&value->v.c.argv, arg); - } - } - return value; + for (size_t i = 0; i < vector_size(root->v.fc.argv); i++) { + Value *arg = ast_to_value(instance, root->v.fc.argv[i]); + if (!arg) { + // TODO: Free argv values + for (size_t i = 0; i < vector_size(value->v.c.argv); i++) { + dcfg_destroy(value->v.c.argv[i]); + } + vector_free(value->v.c.argv); + FREE(value); + return NULL; + } + vector_add(&value->v.c.argv, arg); + } + } + return value; } -dcfg_Value *dcfg_parse(dcfg_Instance *instance, - dcfg_StringView const file_path) { - char path_buf[file_path.size + 1] = {}; - memcpy(path_buf, file_path.data, file_path.size); +dcfg_Value *dcfg_parse(dcfg_Instance *instance, dcfg_StringView const file_path) +{ + char path_buf[file_path.size + 1] = {}; + memcpy(path_buf, file_path.data, file_path.size); - char *abs = instance->realpath(path_buf); - if (!abs) { - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "realpath: %s", strerror(errno)); - } - StringView abs_sv = SV(abs); + char *abs = instance->realpath(path_buf); + if (!abs) { + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "realpath: %s", strerror(errno)); + } + StringView abs_sv = SV(abs); - FILE *fp = instance->fopen(abs, "r"); - if (!fp) { - FREE(abs); - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "fopen: %s", strerror(errno)); - return NULL; - } + FILE *fp = instance->fopen(abs, "r"); + if (!fp) { + FREE(abs); + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "fopen: %s", strerror(errno)); + return NULL; + } - if (instance->fseek(fp, 0, SEEK_END)) { - FREE(abs); - fclose(fp); - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "fseek: %s", strerror(errno)); - return NULL; - } + if (instance->fseek(fp, 0, SEEK_END)) { + FREE(abs); + fclose(fp); + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "fseek: %s", strerror(errno)); + return NULL; + } - long const size = ftell(fp); + long const size = ftell(fp); - if (instance->fseek(fp, 0, SEEK_SET)) { - FREE(abs); - fclose(fp); - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "fseek: %s", strerror(errno)); - return NULL; - } + if (instance->fseek(fp, 0, SEEK_SET)) { + FREE(abs); + fclose(fp); + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "fseek: %s", strerror(errno)); + return NULL; + } - StringView str = { - .size = size, - }; - str.data = ALLOC(size); - if (!fread((void *)str.data, str.size, 1, fp)) { - FREE(abs); - FREE((void *)str.data); - fclose(fp); - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "fread: %s", strerror(errno)); - return NULL; - } + StringView str = { + .size = size, + }; + str.data = ALLOC(size); + if (!fread((void *)str.data, str.size, 1, fp)) { + FREE(abs); + FREE((void *)str.data); + fclose(fp); + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "fread: %s", strerror(errno)); + return NULL; + } - Lexer lexer; - if (!Lexer_init(&lexer, str, abs_sv)) { - FREE(abs); - FREE((void *)str.data); - fclose(fp); - snprintf(instance->last_error, sizeof(instance->last_error) - 1, - "Could not init lexer"); - return NULL; - } + Lexer lexer; + if (!Lexer_init(&lexer, str, abs_sv)) { + FREE(abs); + FREE((void *)str.data); + fclose(fp); + snprintf(instance->last_error, sizeof(instance->last_error) - 1, + "Could not init lexer"); + return NULL; + } - Parser parser; - Parser_init(&parser, &lexer, instance); + Parser parser; + Parser_init(&parser, &lexer, instance); - AST *ast = Parser_parse(&parser); - if (!ast) { - FREE(abs); - FREE((void *)str.data); - fclose(fp); - return NULL; - } + AST *ast = Parser_parse(&parser); + if (!ast) { + FREE(abs); + FREE((void *)str.data); + fclose(fp); + return NULL; + } - Value *v = ast_to_value(instance, ast); - if (!v) { - dcfg_destroy(v); - FREE(abs); - FREE((void *)str.data); - fclose(fp); - return NULL; - } + Value *v = ast_to_value(instance, ast); + if (!v) { + dcfg_destroy(v); + FREE(abs); + FREE((void *)str.data); + fclose(fp); + return NULL; + } - return v; + return v; } -void dcfg_destroy(dcfg_Value *value) { - (void)value; - // FIXME: Implement +void dcfg_destroy(dcfg_Value *value) +{ + (void)value; + // FIXME: Implement } // Libraries