diff options
| author | Chloe M. <chloe@aptel.org> | 2026-08-23 06:37:47 +0000 |
|---|---|---|
| committer | Chloe M. <chloe@aptel.org> | 2026-08-23 06:37:47 +0000 |
| commit | 9bf5da82de7c19360c291d990814128a7b86c92e (patch) | |
| tree | 59b7d7901e3d99e85ede0c45408f14a6f71953cb /core | |
| parent | baff5613531a0e0f8c7397f9b87a8ce1b6e2f5f4 (diff) | |
core: parser: Parse and emit define directives
Signed-off-by: Chloe M. <chloe@aptel.org>
Diffstat (limited to 'core')
| -rw-r--r-- | core/emit.c | 27 | ||||
| -rw-r--r-- | core/parser.c | 116 |
2 files changed, 142 insertions, 1 deletions
diff --git a/core/emit.c b/core/emit.c new file mode 100644 index 0000000..ec00ed2 --- /dev/null +++ b/core/emit.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2026, Apollo Telephone Laboratories. + * Provided under the BSD-3 clause. + */ + +#include <stdio.h> +#include "defconf/emit.h" + +int +emit_data(const char *ident, struct data_value *v) +{ + if (ident == NULL || v == NULL) { + return -1; + } + + switch (v->type) { + case DATA_TYPE_INT: + printf("-D%s=%zu\n", ident, v->v); + return 0; + case DATA_TYPE_STR: + printf("-D%s=\"%s\"\n", ident, v->s); + return 0; + } + + printf("fatal: got bad data value during emission\n"); + return -1; +} diff --git a/core/parser.c b/core/parser.c index 727d5e1..e568504 100644 --- a/core/parser.c +++ b/core/parser.c @@ -6,6 +6,8 @@ #include "defconf/parser.h" #include "defconf/lexer.h" #include "defconf/token.h" +#include "defconf/data.h" +#include "defconf/emit.h" /* Symbolic token */ #define SYMTOK(TOKSTR) \ @@ -31,17 +33,129 @@ static const char *toktab[_TT_MAX] = { [TT_IDENT] = SYMTOK("ident") }; +static int +token_to_data(struct token *tok, struct data_value *result) +{ + if (tok == NULL || result == NULL) { + return -1; + } + + switch (tok->type) { + case TT_TRUE: + result->v = 1; + result->type = DATA_TYPE_INT; + return 0; + case TT_FALSE: + result->v = 0; + result->type = DATA_TYPE_INT; + return 0; + default: + return -1; + } + + return -1; +} + +/* + * Assert that the next token is of a specific type + * + * @state: Defconf state + * @tok: Last token + * @exp: Expected token + */ +static int +parse_expect(struct defconf_state *state, struct token *tok, tt_t exp) +{ + int error; + + if (state == NULL || tok == NULL) { + return -1; + } + + /* Try to grab the next token */ + if ((error = lexer_scan(state, tok)) < 0) { + printf("fatal: expected '%s', got eof\n", TOKSTR(exp)); + return error; + } + + if (tok->type != exp) { + printf("fatal: expected '%s', got %s instead\n", + TOKSTR(exp), TOKSTR(tok->type)); + return -1; + } + + return 0; +} + +/* + * Parse a define directive + * + * @state: Defconf state + * @tok: Last token + * + * Returns zero on success + */ +static int +parse_define(struct defconf_state *state, struct token *tok) +{ + struct data_value value; + char *ident; + int error; + + if (state == NULL || tok == NULL) { + return -1; + } + + /* Expect an identifier */ + if ((error = parse_expect(state, tok, TT_IDENT)) < 0) { + return error; + } + + /* Save the identifier */ + ident = tok->s; + + /* Scan the value */ + if ((error = lexer_scan(state, tok)) < 0) { + printf("fatal: expected value, got eof\n"); + return error; + } + + /* Convert token to data */ + if ((error = token_to_data(tok, &value)) < 0) { + printf("fatal: got bad data [%s]\n", TOKSTR(tok->type)); + return error; + } + + /* Emit the define */ + if ((error = emit_data(ident, &value)) < 0) { + return error; + } + + return 0; +} + int parse_begin(struct defconf_state *state) { struct token tok; + int error; if (state == NULL) { return -1; } while (lexer_scan(state, &tok) == 0) { - printf("got %s\n", TOKSTR(tok.type)); + switch (tok.type) { + case TT_DEFINE: + if ((error = parse_define(state, &tok)) < 0) { + return error; + } + + break; + default: + printf("fatal: got unexpected token: %s\n", TOKSTR(tok.type)); + return -1; + } } return 0; |
