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
+2 -2
View File
@@ -38,14 +38,14 @@ func_arithmetic(lisp_function_gt_eq, >=);
int lisp_function_println(Nodes *args, Scopes *scopes, Node *result) { int lisp_function_println(Nodes *args, Scopes *scopes, Node *result) {
if (args->count != 1) { if (args->count != 1) {
printf("'+' expects one argument!\n"); printf("'+' expects one argument!\n");
return 0; return 1;
} }
eval_one(args->items[0], scopes, result); eval_one(args->items[0], scopes, result);
node_print(*result); node_print(*result);
printf("\n"); printf("\n");
return 1; return 0;
} }
int lisp_function_list(Nodes *args, Scopes *scopes, Node *result) { int lisp_function_list(Nodes *args, Scopes *scopes, Node *result) {
+53 -23
View File
@@ -213,27 +213,49 @@ int parse_one(Tokens *tokens, Node *node) {
node->as_symbol = tok.data; node->as_symbol = tok.data;
} break; } break;
default: { default: {
UNREACHABLE(""); return 1;
} break; }
} }
return 0; return 0;
} }
void parse(Tokens *tokens, Nodes *nodes) { int parse(Tokens *tokens, Nodes *nodes) {
if (nodes == NULL) if (tokens == NULL || nodes == NULL)
return; 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++) { for (size_t i = 0; i < tokens->count; i++) {
if (tokens->items[i].kind == TOKEN_KIND_PAR_LEFT) { TokenKind kind = tokens->items[i].kind;
size_t sub_size = tokens->count - i; 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, Tokens toks = {.count = sub_size,
.capacity = 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}; Node result = {0};
parse_one(&toks, &result); int ret = parse_one(&toks, &result);
if (ret != 0) {
return ret;
}
nob_da_append(nodes, result); nob_da_append(nodes, result);
} }
} }
return 0;
} }
int eval_one(Node input, Scopes *scopes, Node *result) { 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}; 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)) { if (node_is_true(condition)) {
eval_one(children->items[1 + 1], scopes, result); ret = eval_one(children->items[1 + 1], scopes, result);
} else { } 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, if (nob_sv_eq(head.as_symbol,
@@ -291,12 +316,15 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
} }
Node value = {0}; 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) { nob_da_foreach(ScopeObject, scope_object, &globalScope) {
if (nob_sv_eq(scope_object->name, name_node.as_symbol)) { if (nob_sv_eq(scope_object->name, name_node.as_symbol)) {
scope_object->node = value; scope_object->node = value;
result = &children->items[0 + 1]; *result = children->items[0 + 1];
return 0; return 0;
} }
} }
@@ -304,14 +332,17 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
ScopeObject obj = ScopeObject obj =
(ScopeObject){.name = name_node.as_symbol, .node = value}; (ScopeObject){.name = name_node.as_symbol, .node = value};
nob_da_append(&globalScope, obj); nob_da_append(&globalScope, obj);
result = &children->items[0 + 1]; *result = children->items[0 + 1];
return 0; return 0;
} }
Nodes *args = malloc(sizeof(Nodes)); Nodes *args = malloc(sizeof(Nodes));
for (size_t i = 1; i < children->count; i++) { for (size_t i = 1; i < children->count; i++) {
Node n = {0}; 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); nob_da_append(args, n);
} }
@@ -332,16 +363,15 @@ int eval_one(Node input, Scopes *scopes, Node *result) {
return 1; return 1;
} }
default: default:
UNREACHABLE(""); return 1;
} }
return 0;
} }
int eval(Nodes *inputs, Scopes *scopes, Nodes *results) { int eval(Nodes inputs, Scopes *scopes, Nodes *results) {
nob_da_foreach(Node, input, inputs) { nob_da_foreach(Node, input, &inputs) {
Node result = {0}; Node result = {0};
int ret = 0; int ret = eval_one(*input, scopes, &result);
if ((ret = eval_one(*input, scopes, &result)) != 0) { if (ret != 0) {
return ret; return ret;
} }
nob_da_append(results, result); nob_da_append(results, result);
+2 -2
View File
@@ -78,10 +78,10 @@ void build_scopes(Scopes *scopes);
void tokenize(Nob_String_View content, Tokens *tokens); void tokenize(Nob_String_View content, Tokens *tokens);
int parse_one(Tokens *tokens, Node *node); int parse_one(Tokens *tokens, Node *node);
void parse(Tokens *tokens, Nodes *nodes); int parse(Tokens *tokens, Nodes *nodes);
int eval_one(Node input, Scopes *scopes, Node *result); int eval_one(Node input, Scopes *scopes, Node *result);
int eval(Nodes *inputs, Scopes *scopes, Nodes *results); int eval(Nodes inputs, Scopes *scopes, Nodes *results);
// builtins // builtins
int lisp_function_add(Nodes *args, Scopes *scopes, Node *result); int lisp_function_add(Nodes *args, Scopes *scopes, Node *result);
+5 -1
View File
@@ -51,7 +51,11 @@ int main(int argc, char **argv) {
#endif #endif
Nodes evaluated = {0}; Nodes evaluated = {0};
int ret = eval(&result, &scopes, &evaluated); int ret = eval(result, &scopes, &evaluated);
if (ret != 0) {
return 1;
}
nob_da_foreach(Node, node, &evaluated) { nob_da_foreach(Node, node, &evaluated) {
node_print(*node); node_print(*node);
printf("\n"); printf("\n");