fix(parser)

parser used to work depending on opening parenthesis and therefore
parsed e.g. `(if 0 (list 1 2 3) 1)` as two seperate expressions, thus
the example would print:
1
(1 2 3)

Now fixed by using a stack for parenthesis
This commit is contained in:
2026-07-21 20:12:15 +02:00
parent 8ec82a66e0
commit 09b552ed8c
4 changed files with 62 additions and 28 deletions
+53 -23
View File
@@ -213,27 +213,49 @@ int parse_one(Tokens *tokens, Node *node) {
node->as_symbol = tok.data;
} break;
default: {
UNREACHABLE("");
} break;
return 1;
}
}
return 0;
}
void parse(Tokens *tokens, Nodes *nodes) {
if (nodes == NULL)
return;
int parse(Tokens *tokens, Nodes *nodes) {
if (tokens == NULL || nodes == NULL)
return 1;
struct {
size_t *items;
size_t count;
size_t capacity;
} stack = {0};
size_t last_idx = 0;
for (size_t i = 0; i < tokens->count; i++) {
if (tokens->items[i].kind == TOKEN_KIND_PAR_LEFT) {
size_t sub_size = tokens->count - i;
TokenKind kind = tokens->items[i].kind;
if (kind == TOKEN_KIND_PAR_LEFT)
nob_da_append(&stack, i);
else if (kind == TOKEN_KIND_PAR_RIGHT)
last_idx = nob_da_pop(&stack);
if (stack.count == 0) {
size_t sub_size = tokens->count - last_idx;
Tokens toks = {.count = sub_size,
.capacity = sub_size,
.items = tokens->items + i};
.items = tokens->items + last_idx};
printf("Parsing:\n");
nob_da_foreach(Token, token, &toks) {
printf(" %s\n", token_kind_name(token->kind));
}
Node result = {0};
parse_one(&toks, &result);
int ret = parse_one(&toks, &result);
if (ret != 0) {
return ret;
}
nob_da_append(nodes, result);
}
}
return 0;
}
int eval_one(Node input, Scopes *scopes, Node *result) {
@@ -268,14 +290,17 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
}
Node condition = {0};
eval_one(children->items[0 + 1], scopes, &condition);
int ret = eval_one(children->items[0 + 1], scopes, &condition);
if (ret != 0) {
return ret;
}
if (node_is_true(condition)) {
eval_one(children->items[1 + 1], scopes, result);
ret = eval_one(children->items[1 + 1], scopes, result);
} else {
eval_one(children->items[2 + 1], scopes, result);
ret = eval_one(children->items[2 + 1], scopes, result);
}
return 0;
return ret;
}
if (nob_sv_eq(head.as_symbol,
@@ -291,12 +316,15 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
}
Node value = {0};
eval_one(children->items[1 + 1], scopes, &value);
int ret = eval_one(children->items[1 + 1], scopes, &value);
if (ret != 0) {
return ret;
}
nob_da_foreach(ScopeObject, scope_object, &globalScope) {
if (nob_sv_eq(scope_object->name, name_node.as_symbol)) {
scope_object->node = value;
result = &children->items[0 + 1];
*result = children->items[0 + 1];
return 0;
}
}
@@ -304,14 +332,17 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
ScopeObject obj =
(ScopeObject){.name = name_node.as_symbol, .node = value};
nob_da_append(&globalScope, obj);
result = &children->items[0 + 1];
*result = children->items[0 + 1];
return 0;
}
Nodes *args = malloc(sizeof(Nodes));
for (size_t i = 1; i < children->count; i++) {
Node n = {0};
eval_one(children->items[i], scopes, &n);
int ret = eval_one(children->items[i], scopes, &n);
if (ret != 0) {
return ret;
}
nob_da_append(args, n);
}
@@ -332,16 +363,15 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
return 1;
}
default:
UNREACHABLE("");
return 1;
}
return 0;
}
int eval(Nodes *inputs, Scopes *scopes, Nodes *results) {
nob_da_foreach(Node, input, inputs) {
int eval(Nodes inputs, Scopes *scopes, Nodes *results) {
nob_da_foreach(Node, input, &inputs) {
Node result = {0};
int ret = 0;
if ((ret = eval_one(*input, scopes, &result)) != 0) {
int ret = eval_one(*input, scopes, &result);
if (ret != 0) {
return ret;
}
nob_da_append(results, result);