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
|
// File path gets copied internally to instance to a Value * -> path hashmap for
|
||||||
// evaluation.
|
// evaluation.
|
||||||
dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
dcfg_Value *dcfg_parse(
|
||||||
dcfg_StringView const file_path);
|
dcfg_Instance *instance, dcfg_StringView const file_path);
|
||||||
void dcfg_destroy(dcfg_Value *value);
|
void dcfg_destroy(dcfg_Value *value);
|
||||||
|
|
||||||
bool dcfg_serialize_value(dcfg_Value *value, dcfg_StringView *out_sv);
|
bool dcfg_serialize_value(dcfg_Value *value, dcfg_StringView *out_sv);
|
||||||
|
|
||||||
// Value type checking
|
// Value type checking
|
||||||
dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate);
|
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);
|
return dcfg_Value_type_ex(value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value getters
|
// Value getters
|
||||||
bool dcfg_Value_get_object_field_ex(dcfg_Value *value,
|
bool dcfg_Value_get_object_field_ex(dcfg_Value *value,
|
||||||
dcfg_StringView const key,
|
dcfg_StringView const key, dcfg_Value **out_value, bool const evaluate);
|
||||||
dcfg_Value **out_value,
|
|
||||||
bool const evaluate);
|
|
||||||
bool dcfg_Value_get_array_item_ex(dcfg_Value *value, size_t const index,
|
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);
|
||||||
|
|
||||||
@@ -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);
|
size_t *out_count, dcfg_StringView *out_keys);
|
||||||
bool dcfg_Value_get_array_size(dcfg_Value *value, size_t *out_size);
|
bool dcfg_Value_get_array_size(dcfg_Value *value, size_t *out_size);
|
||||||
|
|
||||||
static inline bool dcfg_Value_get_object_field(dcfg_Value *value,
|
static inline bool dcfg_Value_get_object_field(
|
||||||
dcfg_StringView const key,
|
dcfg_Value *value, dcfg_StringView const key, dcfg_Value **out_value)
|
||||||
dcfg_Value **out_value) {
|
{
|
||||||
return dcfg_Value_get_object_field_ex(value, key, out_value, true);
|
return dcfg_Value_get_object_field_ex(value, key, out_value, true);
|
||||||
}
|
}
|
||||||
static inline bool dcfg_Value_get_array_item(dcfg_Value *value,
|
static inline bool dcfg_Value_get_array_item(
|
||||||
size_t const index,
|
dcfg_Value *value, size_t const index, dcfg_Value **out_value)
|
||||||
dcfg_Value **out_value) {
|
{
|
||||||
return dcfg_Value_get_array_item_ex(value, index, out_value, true);
|
return dcfg_Value_get_array_item_ex(value, index, out_value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
165
src/dcfg.c
165
src/dcfg.c
@@ -33,7 +33,8 @@ void pthread_mutex_lock(pthread_mutex_t *);
|
|||||||
void pthread_mutex_unlock(pthread_mutex_t *);
|
void pthread_mutex_unlock(pthread_mutex_t *);
|
||||||
#endif
|
#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);
|
size_t n = strlen(s);
|
||||||
char *clean = malloc(n + 1);
|
char *clean = malloc(n + 1);
|
||||||
if (!clean) {
|
if (!clean) {
|
||||||
@@ -66,7 +67,8 @@ int64_t dcfg_strtoll(const char *s, char **end, int base) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
double dcfg_strtod(const char *s, char **end) {
|
double dcfg_strtod(char const *s, char **end)
|
||||||
|
{
|
||||||
size_t n = strlen(s);
|
size_t n = strlen(s);
|
||||||
char *clean = malloc(n + 1);
|
char *clean = malloc(n + 1);
|
||||||
if (!clean) {
|
if (!clean) {
|
||||||
@@ -105,7 +107,8 @@ 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) {
|
if (a.size != b.size) {
|
||||||
return false;
|
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); }
|
long ftell_(void *f) { return ftell(f); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) {
|
dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info)
|
||||||
|
{
|
||||||
assert(create_info);
|
assert(create_info);
|
||||||
|
|
||||||
dcfg_Instance *instance = calloc(1, sizeof(*instance));
|
dcfg_Instance *instance = calloc(1, sizeof(*instance));
|
||||||
@@ -241,7 +245,8 @@ dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcfg_destroy_instance(dcfg_Instance *instance) {
|
void dcfg_destroy_instance(dcfg_Instance *instance)
|
||||||
|
{
|
||||||
assert(instance);
|
assert(instance);
|
||||||
|
|
||||||
pthread_mutex_lock(&instance->mtx);
|
pthread_mutex_lock(&instance->mtx);
|
||||||
@@ -254,7 +259,8 @@ void dcfg_destroy_instance(dcfg_Instance *instance) {
|
|||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *dcfg_last_error(dcfg_Instance *instance) {
|
char const *dcfg_last_error(dcfg_Instance *instance)
|
||||||
|
{
|
||||||
assert(instance);
|
assert(instance);
|
||||||
|
|
||||||
char const *ret = NULL;
|
char const *ret = NULL;
|
||||||
@@ -314,35 +320,40 @@ typedef struct {
|
|||||||
int offset;
|
int offset;
|
||||||
} Lexer;
|
} 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) {
|
if (pos >= (int)src.size) {
|
||||||
*len = 0;
|
*len = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return (int32_t)utf8proc_iterate((const uint8_t *)src.data + pos,
|
return (int32_t)utf8proc_iterate(
|
||||||
(int)(src.size - pos), len);
|
(uint8_t const *)src.data + pos, (int)(src.size - pos), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_space_cp(int32_t cp) {
|
static inline bool is_space_cp(int32_t cp)
|
||||||
return (cp <= 0x7F &&
|
{
|
||||||
(cp == ' ' || cp == '\t' || cp == '\r' || cp == '\n')) ||
|
return (cp <= 0x7F && (cp == ' ' || cp == '\t' || cp == '\r' || cp == '\n'))
|
||||||
utf8proc_category(cp) == UTF8PROC_CATEGORY_ZS;
|
|| utf8proc_category(cp) == UTF8PROC_CATEGORY_ZS;
|
||||||
}
|
}
|
||||||
static inline bool is_alpha_cp(int32_t cp) {
|
static inline bool is_alpha_cp(int32_t cp)
|
||||||
return (cp <= 0x7F && isalpha(cp)) ||
|
{
|
||||||
(utf8proc_category(cp) >= UTF8PROC_CATEGORY_LU &&
|
return (cp <= 0x7F && isalpha(cp))
|
||||||
utf8proc_category(cp) <= UTF8PROC_CATEGORY_LO);
|
|| (utf8proc_category(cp) >= UTF8PROC_CATEGORY_LU
|
||||||
|
&& utf8proc_category(cp) <= UTF8PROC_CATEGORY_LO);
|
||||||
}
|
}
|
||||||
static inline bool is_digit_cp(int32_t cp) {
|
static inline bool is_digit_cp(int32_t cp)
|
||||||
return (cp <= 0x7F && isdigit(cp)) ||
|
{
|
||||||
utf8proc_category(cp) == UTF8PROC_CATEGORY_ND;
|
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);
|
return is_alpha_cp(cp) || is_digit_cp(cp);
|
||||||
}
|
}
|
||||||
static inline bool is_path_ch_cp(int32_t cp) {
|
static inline bool is_path_ch_cp(int32_t cp)
|
||||||
return cp == '_' || cp == '.' || cp == '/' || cp == '-' || cp == ':' ||
|
{
|
||||||
is_alnum_cp(cp);
|
return cp == '_' || cp == '.' || cp == '/' || cp == '-' || cp == ':'
|
||||||
|
|| is_alnum_cp(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define is_space is_space_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 isdigit_cp is_digit_cp
|
||||||
#define isalnum_cp is_alnum_cp
|
#define isalnum_cp is_alnum_cp
|
||||||
|
|
||||||
static void lex_advance(Lexer *lx) {
|
static void lex_advance(Lexer *lx)
|
||||||
|
{
|
||||||
if (lx->next == -1) {
|
if (lx->next == -1) {
|
||||||
lx->ch = -1;
|
lx->ch = -1;
|
||||||
return;
|
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);
|
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;
|
StringView sv;
|
||||||
sv.data = lx->source.data + start;
|
sv.data = lx->source.data + start;
|
||||||
sv.size = (size_t)(end - start);
|
sv.size = (size_t)(end - start);
|
||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skip_ws_and_comments(Lexer *lx) {
|
static void skip_ws_and_comments(Lexer *lx)
|
||||||
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
while (is_space(lx->ch))
|
while (is_space(lx->ch))
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
@@ -390,7 +404,8 @@ static void skip_ws_and_comments(Lexer *lx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token make_token(TokenType t, Lexer *lx, int start, int end) {
|
static Token make_token(TokenType t, Lexer *lx, int start, int end)
|
||||||
|
{
|
||||||
Token tk = { 0 };
|
Token tk = { 0 };
|
||||||
tk.type = t;
|
tk.type = t;
|
||||||
tk.location.fp = lx->fp;
|
tk.location.fp = lx->fp;
|
||||||
@@ -419,7 +434,8 @@ static Token make_token(TokenType t, Lexer *lx, int start, int end) {
|
|||||||
return tk;
|
return tk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token lex_number(Lexer *lx) {
|
static Token lex_number(Lexer *lx)
|
||||||
|
{
|
||||||
int start = lx->offset;
|
int start = lx->offset;
|
||||||
bool real = false;
|
bool real = false;
|
||||||
|
|
||||||
@@ -431,18 +447,20 @@ static Token lex_number(Lexer *lx) {
|
|||||||
while (isdigit_cp(lx->ch) || lx->ch == '_')
|
while (isdigit_cp(lx->ch) || lx->ch == '_')
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
}
|
}
|
||||||
return make_token(real ? TokenType_Real : TokenType_Integer, lx, start,
|
return make_token(
|
||||||
lx->offset);
|
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;
|
int start = lx->offset;
|
||||||
while (isalnum_cp(lx->ch) || lx->ch == '_')
|
while (isalnum_cp(lx->ch) || lx->ch == '_')
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
return make_token(TokenType_Identifier, lx, start, lx->offset);
|
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;
|
int quote = lx->ch;
|
||||||
lex_advance(lx); // skip opening quote
|
lex_advance(lx); // skip opening quote
|
||||||
int start = lx->offset;
|
int start = lx->offset;
|
||||||
@@ -457,7 +475,8 @@ static Token lex_string(Lexer *lx) {
|
|||||||
return make_token(TokenType_String, lx, start, end);
|
return make_token(TokenType_String, lx, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token lex_path(Lexer *lx) {
|
static Token lex_path(Lexer *lx)
|
||||||
|
{
|
||||||
int start = lx->offset;
|
int start = lx->offset;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (lx->ch == '\\') {
|
if (lx->ch == '\\') {
|
||||||
@@ -472,7 +491,8 @@ static Token lex_path(Lexer *lx) {
|
|||||||
return make_token(TokenType_Path, lx, start, lx->offset);
|
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);
|
memset(lx, 0, sizeof *lx);
|
||||||
lx->source = src;
|
lx->source = src;
|
||||||
lx->fp = fp;
|
lx->fp = fp;
|
||||||
@@ -483,7 +503,8 @@ bool Lexer_init(Lexer *lx, StringView src, StringView fp) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token Lexer_next(Lexer *lx) {
|
Token Lexer_next(Lexer *lx)
|
||||||
|
{
|
||||||
skip_ws_and_comments(lx);
|
skip_ws_and_comments(lx);
|
||||||
int start_off = lx->offset;
|
int start_off = lx->offset;
|
||||||
|
|
||||||
@@ -495,9 +516,9 @@ Token Lexer_next(Lexer *lx) {
|
|||||||
|
|
||||||
if (lx->ch == '/' // "/foo"
|
if (lx->ch == '/' // "/foo"
|
||||||
|| (lx->ch == '.' && lx->next == '/') // "./foo"
|
|| (lx->ch == '.' && lx->next == '/') // "./foo"
|
||||||
|| (lx->ch == '.' && lx->offset + 2 < (int)lx->source.size &&
|
|| (lx->ch == '.' && lx->offset + 2 < (int)lx->source.size
|
||||||
lx->source.data[lx->offset + 1] == '.' &&
|
&& lx->source.data[lx->offset + 1] == '.'
|
||||||
lx->source.data[lx->offset + 2] == '/') // "../foo"
|
&& lx->source.data[lx->offset + 2] == '/') // "../foo"
|
||||||
|| (isalpha_cp(lx->ch) && lx->next == ':')) { // "C:/foo"
|
|| (isalpha_cp(lx->ch) && lx->next == ':')) { // "C:/foo"
|
||||||
return lex_path(lx);
|
return lex_path(lx);
|
||||||
}
|
}
|
||||||
@@ -611,7 +632,8 @@ typedef struct {
|
|||||||
Token cur, next;
|
Token cur, next;
|
||||||
} Parser;
|
} Parser;
|
||||||
|
|
||||||
bool Parser_next(Parser *parser) {
|
bool Parser_next(Parser *parser)
|
||||||
|
{
|
||||||
parser->cur = parser->next;
|
parser->cur = parser->next;
|
||||||
parser->next = Lexer_next(parser->lexer);
|
parser->next = Lexer_next(parser->lexer);
|
||||||
bool ret = parser->next.type != TokenType_Error;
|
bool ret = parser->next.type != TokenType_Error;
|
||||||
@@ -621,7 +643,8 @@ bool Parser_next(Parser *parser) {
|
|||||||
return ret;
|
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->lexer = lexer;
|
||||||
out_parser->instance = instance;
|
out_parser->instance = instance;
|
||||||
if (!Parser_next(out_parser)) {
|
if (!Parser_next(out_parser)) {
|
||||||
@@ -633,8 +656,8 @@ bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser_accept(Parser *parser, TokenType type,
|
bool Parser_accept(Parser *parser, TokenType type, SourceLocation *out_location)
|
||||||
SourceLocation *out_location) {
|
{
|
||||||
if (parser->cur.type == type) {
|
if (parser->cur.type == type) {
|
||||||
if (out_location) {
|
if (out_location) {
|
||||||
*out_location = parser->cur.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 ALLOC(sz) (parser->instance->alloc((sz)))
|
||||||
#define FREE(ptr) (parser->instance->free((ptr)))
|
#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);
|
assert(parser);
|
||||||
if (!ast) {
|
if (!ast) {
|
||||||
return;
|
return;
|
||||||
@@ -691,10 +715,11 @@ void AST_free_parser(AST *ast, Parser *parser) {
|
|||||||
FREE(ast);
|
FREE(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
AST *parser_parse_dot_access(Parser *parser, StringView *current) {
|
AST *parser_parse_dot_access(Parser *parser, StringView *current)
|
||||||
|
{
|
||||||
assert(parser);
|
assert(parser);
|
||||||
assert(parser->cur.type == TokenType_Identifier ||
|
assert(parser->cur.type == TokenType_Identifier
|
||||||
parser->cur.type == TokenType_String);
|
|| parser->cur.type == TokenType_String);
|
||||||
|
|
||||||
StringView *accessv = vector_create();
|
StringView *accessv = vector_create();
|
||||||
if (!accessv) {
|
if (!accessv) {
|
||||||
@@ -708,8 +733,8 @@ AST *parser_parse_dot_access(Parser *parser, StringView *current) {
|
|||||||
SourceLocation loc = parser->cur.location;
|
SourceLocation loc = parser->cur.location;
|
||||||
SourceLocation last_loc = parser->cur.location;
|
SourceLocation last_loc = parser->cur.location;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (parser->cur.type != TokenType_Identifier &&
|
if (parser->cur.type != TokenType_Identifier
|
||||||
parser->cur.type != TokenType_String) {
|
&& parser->cur.type != TokenType_String) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,7 +770,8 @@ AST *parser_parse_dot_access(Parser *parser, StringView *current) {
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST *parser_parse_value(Parser *parser) {
|
AST *parser_parse_value(Parser *parser)
|
||||||
|
{
|
||||||
AST *ast = ALLOC(sizeof(*ast));
|
AST *ast = ALLOC(sizeof(*ast));
|
||||||
ast->location = parser->cur.location;
|
ast->location = parser->cur.location;
|
||||||
if (parser->cur.type == TokenType_Integer) {
|
if (parser->cur.type == TokenType_Integer) {
|
||||||
@@ -754,8 +780,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
} else if (parser->cur.type == TokenType_Real) {
|
} else if (parser->cur.type == TokenType_Real) {
|
||||||
ast->kind = ASTKind_Real;
|
ast->kind = ASTKind_Real;
|
||||||
ast->v.r = parser->cur.v.r;
|
ast->v.r = parser->cur.v.r;
|
||||||
} else if (parser->cur.type == TokenType_String ||
|
} else if (parser->cur.type == TokenType_String
|
||||||
parser->cur.type == TokenType_Identifier) {
|
|| parser->cur.type == TokenType_Identifier) {
|
||||||
ast->kind = ASTKind_Key;
|
ast->kind = ASTKind_Key;
|
||||||
ast->v.s = parser->cur.v.s;
|
ast->v.s = parser->cur.v.s;
|
||||||
|
|
||||||
@@ -765,7 +791,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
} else if (parser->cur.type == TokenType_Identifier) {
|
} else if (parser->cur.type == TokenType_Identifier) {
|
||||||
if (sv_eq(ast->v.s, SV("fn"))) {
|
if (sv_eq(ast->v.s, SV("fn"))) {
|
||||||
if (!Parser_next(parser)) {
|
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);
|
FREE(ast);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -773,7 +800,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
ast->kind = ASTKind_Function;
|
ast->kind = ASTKind_Function;
|
||||||
ast->v.f.argv = vector_create();
|
ast->v.f.argv = vector_create();
|
||||||
if (!ast->v.f.argv) {
|
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);
|
FREE(ast);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -802,10 +830,12 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
}
|
}
|
||||||
ast->location.range.end = ast->v.f.body->location.range.end;
|
ast->location.range.end = ast->v.f.body->location.range.end;
|
||||||
return ast;
|
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->kind = ASTKind_Boolean;
|
||||||
ast->v.b = true;
|
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->kind = ASTKind_Boolean;
|
||||||
ast->v.b = false;
|
ast->v.b = false;
|
||||||
}
|
}
|
||||||
@@ -854,8 +884,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->cur.type != TokenType_Identifier &&
|
if (parser->cur.type != TokenType_Identifier
|
||||||
parser->cur.type != TokenType_String) {
|
&& parser->cur.type != TokenType_String) {
|
||||||
strcpy(parser->instance->last_error,
|
strcpy(parser->instance->last_error,
|
||||||
"Expected identifier or string for object key");
|
"Expected identifier or string for object key");
|
||||||
vector_free(ast->v.bl.entryv);
|
vector_free(ast->v.bl.entryv);
|
||||||
@@ -865,7 +895,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
|
|
||||||
AST *key = parser_parse_dot_access(parser, NULL);
|
AST *key = parser_parse_dot_access(parser, NULL);
|
||||||
if (!Parser_accept(parser, TokenType_Set, 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);
|
vector_free(ast->v.bl.entryv);
|
||||||
FREE(ast);
|
FREE(ast);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -879,7 +910,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key);
|
assert(
|
||||||
|
key->kind == ASTKind_MemberAccess || key->kind == ASTKind_Key);
|
||||||
ASTBlock_Entry entry = {
|
ASTBlock_Entry entry = {
|
||||||
.k = key,
|
.k = key,
|
||||||
.v = value,
|
.v = value,
|
||||||
@@ -921,7 +953,8 @@ AST *parser_parse_value(Parser *parser) {
|
|||||||
return ast;
|
return ast;
|
||||||
} else {
|
} else {
|
||||||
if (parser->cur.type == TokenType_End) {
|
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 {
|
} else {
|
||||||
strcpy(parser->instance->last_error, "Unexpected token for value");
|
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 ALLOC(sz) (instance->alloc((sz)))
|
||||||
#define FREE(ptr) (instance->free((ptr)))
|
#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 *value = ALLOC(sizeof(*value));
|
||||||
value->instance = instance;
|
value->instance = instance;
|
||||||
if (root->kind == ASTKind_Key) {
|
if (root->kind == ASTKind_Key) {
|
||||||
@@ -1028,8 +1062,8 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
dcfg_Value *dcfg_parse(dcfg_Instance *instance, dcfg_StringView const file_path)
|
||||||
dcfg_StringView const file_path) {
|
{
|
||||||
char path_buf[file_path.size + 1] = {};
|
char path_buf[file_path.size + 1] = {};
|
||||||
memcpy(path_buf, file_path.data, file_path.size);
|
memcpy(path_buf, file_path.data, file_path.size);
|
||||||
|
|
||||||
@@ -1112,7 +1146,8 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcfg_destroy(dcfg_Value *value) {
|
void dcfg_destroy(dcfg_Value *value)
|
||||||
|
{
|
||||||
(void)value;
|
(void)value;
|
||||||
// FIXME: Implement
|
// FIXME: Implement
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user