26
.clang-format
Normal file
26
.clang-format
Normal file
@@ -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
|
@@ -57,23 +57,22 @@ 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) {
|
||||
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);
|
||||
|
||||
@@ -86,14 +85,14 @@ bool dcfg_Value_get_object_keys(dcfg_Value *value, size_t const capacity,
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
187
src/dcfg.c
187
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 <assert.h>
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DCFG_PTHREAD_SUPPORT
|
||||
#include <pthread.h>
|
||||
# include <pthread.h>
|
||||
#else
|
||||
typedef struct {
|
||||
int unused;
|
||||
@@ -33,7 +33,8 @@ 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) {
|
||||
int64_t dcfg_strtoll(const char *s, char **end, int base)
|
||||
{
|
||||
size_t n = strlen(s);
|
||||
char *clean = malloc(n + 1);
|
||||
if (!clean) {
|
||||
@@ -66,7 +67,8 @@ int64_t dcfg_strtoll(const char *s, char **end, int base) {
|
||||
return v;
|
||||
}
|
||||
|
||||
double dcfg_strtod(const char *s, char **end) {
|
||||
double dcfg_strtod(char const *s, char **end)
|
||||
{
|
||||
size_t n = strlen(s);
|
||||
char *clean = malloc(n + 1);
|
||||
if (!clean) {
|
||||
@@ -103,9 +105,10 @@ 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) {
|
||||
static inline bool sv_eq(StringView a, StringView b)
|
||||
{
|
||||
if (a.size != b.size) {
|
||||
return false;
|
||||
}
|
||||
@@ -199,7 +202,8 @@ 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) {
|
||||
dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info)
|
||||
{
|
||||
assert(create_info);
|
||||
|
||||
dcfg_Instance *instance = calloc(1, sizeof(*instance));
|
||||
@@ -241,7 +245,8 @@ dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void dcfg_destroy_instance(dcfg_Instance *instance) {
|
||||
void dcfg_destroy_instance(dcfg_Instance *instance)
|
||||
{
|
||||
assert(instance);
|
||||
|
||||
pthread_mutex_lock(&instance->mtx);
|
||||
@@ -254,7 +259,8 @@ void dcfg_destroy_instance(dcfg_Instance *instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
char const *dcfg_last_error(dcfg_Instance *instance) {
|
||||
char const *dcfg_last_error(dcfg_Instance *instance)
|
||||
{
|
||||
assert(instance);
|
||||
|
||||
char const *ret = NULL;
|
||||
@@ -314,35 +320,40 @@ typedef struct {
|
||||
int offset;
|
||||
} Lexer;
|
||||
|
||||
static inline int32_t decode_cp(StringView src, int pos, int *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((const uint8_t *)src.data + pos,
|
||||
(int)(src.size - pos), len);
|
||||
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) {
|
||||
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,7 +362,8 @@ 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) {
|
||||
static void lex_advance(Lexer *lx)
|
||||
{
|
||||
if (lx->next == -1) {
|
||||
lx->ch = -1;
|
||||
return;
|
||||
@@ -370,14 +382,16 @@ static void lex_advance(Lexer *lx) {
|
||||
lx->next = decode_cp(lx->source, lx->offset + lx->ch_len, &lx->next_len);
|
||||
}
|
||||
|
||||
static StringView lex_slice(Lexer *lx, int start, int end) {
|
||||
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) {
|
||||
static void skip_ws_and_comments(Lexer *lx)
|
||||
{
|
||||
for (;;) {
|
||||
while (is_space(lx->ch))
|
||||
lex_advance(lx);
|
||||
@@ -390,8 +404,9 @@ static void skip_ws_and_comments(Lexer *lx) {
|
||||
}
|
||||
}
|
||||
|
||||
static Token make_token(TokenType t, Lexer *lx, int start, int end) {
|
||||
Token tk = {0};
|
||||
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;
|
||||
@@ -419,7 +434,8 @@ static Token make_token(TokenType t, Lexer *lx, int start, int end) {
|
||||
return tk;
|
||||
}
|
||||
|
||||
static Token lex_number(Lexer *lx) {
|
||||
static Token lex_number(Lexer *lx)
|
||||
{
|
||||
int start = lx->offset;
|
||||
bool real = false;
|
||||
|
||||
@@ -431,18 +447,20 @@ static Token lex_number(Lexer *lx) {
|
||||
while (isdigit_cp(lx->ch) || lx->ch == '_')
|
||||
lex_advance(lx);
|
||||
}
|
||||
return make_token(real ? TokenType_Real : TokenType_Integer, lx, start,
|
||||
lx->offset);
|
||||
return make_token(
|
||||
real ? TokenType_Real : TokenType_Integer, lx, start, lx->offset);
|
||||
}
|
||||
|
||||
static Token lex_identifier(Lexer *lx) {
|
||||
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) {
|
||||
static Token lex_string(Lexer *lx)
|
||||
{
|
||||
int quote = lx->ch;
|
||||
lex_advance(lx); // skip opening quote
|
||||
int start = lx->offset;
|
||||
@@ -457,7 +475,8 @@ static Token lex_string(Lexer *lx) {
|
||||
return make_token(TokenType_String, lx, start, end);
|
||||
}
|
||||
|
||||
static Token lex_path(Lexer *lx) {
|
||||
static Token lex_path(Lexer *lx)
|
||||
{
|
||||
int start = lx->offset;
|
||||
for (;;) {
|
||||
if (lx->ch == '\\') {
|
||||
@@ -472,32 +491,34 @@ static Token lex_path(Lexer *lx) {
|
||||
return make_token(TokenType_Path, lx, start, lx->offset);
|
||||
}
|
||||
|
||||
bool Lexer_init(Lexer *lx, StringView src, StringView fp) {
|
||||
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->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;
|
||||
}
|
||||
|
||||
Token Lexer_next(Lexer *lx) {
|
||||
Token Lexer_next(Lexer *lx)
|
||||
{
|
||||
skip_ws_and_comments(lx);
|
||||
int start_off = lx->offset;
|
||||
|
||||
if (lx->ch == -1) {
|
||||
Token tk = {.type = TokenType_End};
|
||||
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"
|
||||
|| (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);
|
||||
}
|
||||
@@ -539,7 +560,7 @@ Token Lexer_next(Lexer *lx) {
|
||||
if (isdigit_cp(lx->ch))
|
||||
return lex_number(lx);
|
||||
|
||||
Token err = {.type = TokenType_Error};
|
||||
Token err = { .type = TokenType_Error };
|
||||
err.location.fp = lx->fp;
|
||||
lex_advance(lx);
|
||||
return err;
|
||||
@@ -611,7 +632,8 @@ typedef struct {
|
||||
Token cur, next;
|
||||
} Parser;
|
||||
|
||||
bool Parser_next(Parser *parser) {
|
||||
bool Parser_next(Parser *parser)
|
||||
{
|
||||
parser->cur = parser->next;
|
||||
parser->next = Lexer_next(parser->lexer);
|
||||
bool ret = parser->next.type != TokenType_Error;
|
||||
@@ -621,7 +643,8 @@ bool Parser_next(Parser *parser) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance) {
|
||||
bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance)
|
||||
{
|
||||
out_parser->lexer = lexer;
|
||||
out_parser->instance = instance;
|
||||
if (!Parser_next(out_parser)) {
|
||||
@@ -633,8 +656,8 @@ bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser_accept(Parser *parser, TokenType type,
|
||||
SourceLocation *out_location) {
|
||||
bool Parser_accept(Parser *parser, TokenType type, SourceLocation *out_location)
|
||||
{
|
||||
if (parser->cur.type == type) {
|
||||
if (out_location) {
|
||||
*out_location = parser->cur.location;
|
||||
@@ -652,7 +675,8 @@ 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) {
|
||||
void AST_free_parser(AST *ast, Parser *parser)
|
||||
{
|
||||
assert(parser);
|
||||
if (!ast) {
|
||||
return;
|
||||
@@ -691,10 +715,11 @@ void AST_free_parser(AST *ast, Parser *parser) {
|
||||
FREE(ast);
|
||||
}
|
||||
|
||||
AST *parser_parse_dot_access(Parser *parser, StringView *current) {
|
||||
AST *parser_parse_dot_access(Parser *parser, StringView *current)
|
||||
{
|
||||
assert(parser);
|
||||
assert(parser->cur.type == TokenType_Identifier ||
|
||||
parser->cur.type == TokenType_String);
|
||||
assert(parser->cur.type == TokenType_Identifier
|
||||
|| parser->cur.type == TokenType_String);
|
||||
|
||||
StringView *accessv = vector_create();
|
||||
if (!accessv) {
|
||||
@@ -708,8 +733,8 @@ AST *parser_parse_dot_access(Parser *parser, StringView *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) {
|
||||
if (parser->cur.type != TokenType_Identifier
|
||||
&& parser->cur.type != TokenType_String) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -745,7 +770,8 @@ AST *parser_parse_dot_access(Parser *parser, StringView *current) {
|
||||
return ast;
|
||||
}
|
||||
|
||||
AST *parser_parse_value(Parser *parser) {
|
||||
AST *parser_parse_value(Parser *parser)
|
||||
{
|
||||
AST *ast = ALLOC(sizeof(*ast));
|
||||
ast->location = parser->cur.location;
|
||||
if (parser->cur.type == TokenType_Integer) {
|
||||
@@ -754,8 +780,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
} 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) {
|
||||
} else if (parser->cur.type == TokenType_String
|
||||
|| parser->cur.type == TokenType_Identifier) {
|
||||
ast->kind = ASTKind_Key;
|
||||
ast->v.s = parser->cur.v.s;
|
||||
|
||||
@@ -765,7 +791,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
} 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");
|
||||
strcpy(parser->instance->last_error,
|
||||
"Failed to advance fn keyword");
|
||||
FREE(ast);
|
||||
return NULL;
|
||||
}
|
||||
@@ -773,7 +800,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
ast->kind = ASTKind_Function;
|
||||
ast->v.f.argv = vector_create();
|
||||
if (!ast->v.f.argv) {
|
||||
strcpy(parser->instance->last_error, "Failed to allocate vector");
|
||||
strcpy(parser->instance->last_error,
|
||||
"Failed to allocate vector");
|
||||
FREE(ast);
|
||||
return NULL;
|
||||
}
|
||||
@@ -802,10 +830,12 @@ AST *parser_parse_value(Parser *parser) {
|
||||
}
|
||||
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"))) {
|
||||
} 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"))) {
|
||||
} else if (sv_eq(ast->v.s, SV("off"))
|
||||
|| sv_eq(ast->v.s, SV("false"))) {
|
||||
ast->kind = ASTKind_Boolean;
|
||||
ast->v.b = false;
|
||||
}
|
||||
@@ -854,8 +884,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (parser->cur.type != TokenType_Identifier &&
|
||||
parser->cur.type != TokenType_String) {
|
||||
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);
|
||||
@@ -865,7 +895,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
|
||||
AST *key = parser_parse_dot_access(parser, NULL);
|
||||
if (!Parser_accept(parser, TokenType_Set, NULL)) {
|
||||
strcpy(parser->instance->last_error, "Expected = after object key");
|
||||
strcpy(parser->instance->last_error,
|
||||
"Expected = after object key");
|
||||
vector_free(ast->v.bl.entryv);
|
||||
FREE(ast);
|
||||
return NULL;
|
||||
@@ -879,7 +910,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key);
|
||||
assert(
|
||||
key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key);
|
||||
ASTBlock_Entry entry = {
|
||||
.k = key,
|
||||
.v = value,
|
||||
@@ -921,7 +953,8 @@ AST *parser_parse_value(Parser *parser) {
|
||||
return ast;
|
||||
} else {
|
||||
if (parser->cur.type == TokenType_End) {
|
||||
strcpy(parser->instance->last_error, "Expected value, got end of file");
|
||||
strcpy(parser->instance->last_error,
|
||||
"Expected value, got end of file");
|
||||
} else {
|
||||
strcpy(parser->instance->last_error, "Unexpected token for value");
|
||||
}
|
||||
@@ -945,7 +978,8 @@ 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 *ast_to_value(dcfg_Instance *instance, AST *root)
|
||||
{
|
||||
Value *value = ALLOC(sizeof(*value));
|
||||
value->instance = instance;
|
||||
if (root->kind == ASTKind_Key) {
|
||||
@@ -1028,8 +1062,8 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root) {
|
||||
return value;
|
||||
}
|
||||
|
||||
dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
||||
dcfg_StringView const file_path) {
|
||||
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);
|
||||
|
||||
@@ -1112,7 +1146,8 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
||||
return v;
|
||||
}
|
||||
|
||||
void dcfg_destroy(dcfg_Value *value) {
|
||||
void dcfg_destroy(dcfg_Value *value)
|
||||
{
|
||||
(void)value;
|
||||
// FIXME: Implement
|
||||
}
|
||||
|
Reference in New Issue
Block a user