From f69fb284ec8ca37c2e53194287f556bec6b73fd2 Mon Sep 17 00:00:00 2001 From: sfja Date: Thu, 1 Oct 2026 23:55:04 +0200 Subject: [PATCH] initial parse --- ast_print.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++ resolve.c | 93 +++++++++++++ resolve.h | 13 ++ 3 files changed, 474 insertions(+) create mode 100644 ast_print.c create mode 100644 resolve.c create mode 100644 resolve.h diff --git a/ast_print.c b/ast_print.c new file mode 100644 index 0000000..af70782 --- /dev/null +++ b/ast_print.c @@ -0,0 +1,368 @@ +#include "ast.h" +#include "collection.h" +#include +#include +#include + +static void indent(FILE* f, int depth) +{ + for (int i = 0; i < depth; ++i) { + fprintf(f, " "); + } +} + +void ast_stmt_block_print(FILE* f, const AstStmtBlock* node, int depth) +{ + fprintf(f, "StmtBlock %d:%d {\n", node->loc.line, node->loc.col); + indent(f, depth + 1); + fprintf(f, "stmts: ["); + + if (node->stmts_size) { + fprintf(f, "\n"); + for (size_t i = 0; i < node->stmts_size; ++i) { + indent(f, depth + 2); + ast_stmt_print(f, node->stmts[i], depth + 2); + fprintf(f, ",\n"); + } + indent(f, depth + 1); + } + fprintf(f, "],\n"); + + indent(f, depth); + fprintf(f, "}"); +} + +void ast_stmt_print(FILE* f, const AstStmt* node, int depth) +{ + switch (node->ty) { + case AstStmt_Decl: { + fprintf(f, "Stmt::Decl %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "decl: "); + ast_decl_print(f, node->decl, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth); + fprintf(f, "}"); + break; + } + case AstStmt_Expr: { + fprintf(f, "Stmt::Expr %d:%d {\n", node->loc.line, node->loc.col); + indent(f, depth + 1); + + fprintf(f, "expr: "); + + ast_expr_print(f, node->expr, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth); + fprintf(f, "}"); + break; + } + } +} + +static void spec_print(FILE* f, AstSpec spec) +{ + struct { + AstSpec specifier; + const char* ident; + } spec_idents[] = { + { AstSpec_Int, "int" }, + { AstSpec_Char, "char" }, + { AstSpec_Unsigned, "unsigned" }, + { AstSpec_Static, "static" }, + { AstSpec_Const, "const" }, + { AstSpec_Inline, "inline" }, + { AstSpec_Typedef, "typedef" }, + { AstSpec_Enum, "enum" }, + { AstSpec_Struct, "struct" }, + { AstSpec_Union, "union" }, + }; + + bool first = true; + + for (size_t i = 0; i < sizeof(spec_idents) / sizeof(spec_idents[0]); ++i) { + if (spec & spec_idents[i].specifier) { + if (!first) + fprintf(f, " "); + first = false; + fprintf(f, "%s", spec_idents[i].ident); + } + } +} + +void ast_decl_print(FILE* f, const AstDecl* node, int depth) +{ + fprintf(f, "Decl %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "spec: ["); + spec_print(f, node->spec); + fprintf(f, "],\n"); + + if (node->spec & AstSpec_DefTy) { + assert(node->type_ident); + indent(f, depth + 1); + fprintf(f, "type_ident: \"%s\",\n", node->type_ident); + } + + indent(f, depth + 1); + fprintf(f, "declars: ["); + if (node->declars_size) { + fprintf(f, "\n"); + + for (size_t i = 0; i < node->declars_size; ++i) { + indent(f, depth + 2); + ast_declar_print(f, node->declars[i], depth + 2); + fprintf(f, ",\n"); + } + + indent(f, depth + 1); + } + fprintf(f, "],\n"); + + if (node->function_body) { + indent(f, depth + 1); + fprintf(f, "function_body: "); + ast_stmt_block_print(f, node->function_body, depth + 1); + fprintf(f, ",\n"); + } + + indent(f, depth); + fprintf(f, "}"); +} + +void ast_declar_print(FILE* f, const AstDeclar* node, int depth) +{ + switch (node->ty) { + case AstDeclar_Ident: { + fprintf( + f, "Declar::Ident %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "ident: \"%s\",\n", node->ident); + + break; + } + case AstDeclar_Pointer: { + fprintf( + f, "Declar::Pointer %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "declar: "); + ast_declar_print(f, node->pointer.declar, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth + 1); + fprintf(f, "spec: ["); + spec_print(f, node->pointer.spec); + fprintf(f, "],\n"); + + break; + } + case AstDeclar_Array: { + fprintf( + f, "Declar::Array %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "declar: "); + ast_declar_print(f, node->array.declar, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth + 1); + fprintf(f, "expr: "); + ast_expr_print(f, node->array.expr, depth + 1); + fprintf(f, ",\n"); + + break; + } + case AstDeclar_Function: { + fprintf( + f, "Declar::Function %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "declar: "); + ast_declar_print(f, node->array.declar, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth + 1); + fprintf(f, "params: ["); + if (node->function.params_size) { + fprintf(f, "\n"); + + for (size_t i = 0; i < node->function.params_size; ++i) { + indent(f, depth + 2); + ast_decl_print(f, node->function.params[i], depth + 2); + fprintf(f, ",\n"); + } + + indent(f, depth + 1); + fprintf(f, "],\n"); + } else { + fprintf(f, "],\n"); + } + + break; + } + } + + if (node->init_expr) { + indent(f, depth + 2); + fprintf(f, "decl: "); + ast_expr_print(f, node->init_expr, depth + 2); + fprintf(f, ",\n"); + } + + indent(f, depth); + fprintf(f, "}"); +} + +void ast_expr_print(FILE* f, const AstExpr* node, int depth) +{ + switch (node->ty) { + case AstExpr_Ident: { + fprintf(f, "Expr::Ident %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "ident: \"%s\",\n", node->ident); + + indent(f, depth); + fprintf(f, "}"); + break; + } + case AstExpr_Str: { + fprintf(f, "Expr::Str %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "str_val: \"%s\",\n", node->str_val); + + indent(f, depth); + fprintf(f, "}"); + break; + } + case AstExpr_Call: { + fprintf(f, "Expr::Call %d:%d {\n", node->loc.line, node->loc.col); + + indent(f, depth + 1); + fprintf(f, "expr: "); + ast_expr_print(f, node->call.expr, depth + 1); + fprintf(f, ",\n"); + + indent(f, depth + 1); + fprintf(f, "args: ["); + + if (node->call.args_size) { + fprintf(f, "\n"); + for (size_t i = 0; i < node->call.args_size; ++i) { + indent(f, depth + 2); + ast_expr_print(f, node->call.args[i], depth + 2); + fprintf(f, ",\n"); + } + indent(f, depth + 1); + } + fprintf(f, ",]\n"); + + indent(f, depth); + fprintf(f, "}"); + break; + } + } +} + +void ast_stmt_block_visit(AstVisitor* v, AstStmtBlock* node) +{ + if (v->visit_stmt_block && v->visit_stmt_block(v, node) == AstVisitor_Break) + return; + ast_stmt_block_visit_body(v, node); +} + +void ast_stmt_block_visit_body(AstVisitor* v, AstStmtBlock* node) +{ + for (size_t i = 0; i < node->stmts_size; ++i) { + ast_stmt_visit(v, node->stmts[i]); + } +} + +void ast_stmt_visit(AstVisitor* v, AstStmt* node) +{ + if (v->visit_stmt && v->visit_stmt(v, node) == AstVisitor_Break) + return; + ast_stmt_visit_body(v, node); +} + +void ast_stmt_visit_body(AstVisitor* v, AstStmt* node) +{ + switch (node->ty) { + case AstStmt_Decl: + ast_decl_visit(v, node->decl); + break; + case AstStmt_Expr: + ast_expr_visit(v, node->expr); + break; + } +} + +void ast_decl_visit(AstVisitor* v, AstDecl* node) +{ + if (v->visit_decl && v->visit_decl(v, node) == AstVisitor_Break) + return; + ast_decl_visit_body(v, node); +} + +void ast_decl_visit_body(AstVisitor* v, AstDecl* node) +{ + for (size_t i = 0; i < node->declars_size; ++i) + ast_declar_visit(v, node->declars[i]); +} + +void ast_declar_visit(AstVisitor* v, AstDeclar* node) +{ + if (v->visit_declar && v->visit_declar(v, node) == AstVisitor_Break) + return; + ast_declar_visit_body(v, node); +} + +void ast_declar_visit_body(AstVisitor* v, AstDeclar* node) +{ + switch (node->ty) { + case AstDeclar_Ident: + break; + case AstDeclar_Pointer: + ast_declar_visit(v, node->pointer.declar); + break; + case AstDeclar_Array: + ast_declar_visit(v, node->array.declar); + ast_expr_visit(v, node->array.expr); + break; + case AstDeclar_Function: + ast_declar_visit(v, node->pointer.declar); + for (size_t i = 0; i < node->function.params_size; ++i) + ast_decl_visit(v, node->function.params[i]); + break; + } +} + +void ast_expr_visit(AstVisitor* v, AstExpr* node) +{ + if (v->visit_expr && v->visit_expr(v, node) == AstVisitor_Break) + return; + ast_expr_visit_body(v, node); +} + +void ast_expr_visit_body(AstVisitor* v, AstExpr* node) +{ + + switch (node->ty) { + case AstExpr_Ident: + break; + case AstExpr_Str: + break; + case AstExpr_Call: + ast_expr_visit(v, node->call.expr); + for (size_t i = 0; i < node->call.args_size; ++i) + ast_expr_visit(v, node->call.args[i]); + break; + } +} diff --git a/resolve.c b/resolve.c new file mode 100644 index 0000000..cc4849a --- /dev/null +++ b/resolve.c @@ -0,0 +1,93 @@ +#include "resolve.h" +#include "ast.h" +#include "syms.h" +#include +#include + +struct Resolver { + Syms* ord_syms; + Syms* tag_syms; + Syms* label_syms; + + bool in_typedef; +}; + +Resolver* resolver_new() +{ + Resolver* r = malloc(sizeof(Resolver)); + *r = (Resolver) { + .ord_syms = syms_new(), + .tag_syms = syms_new(), + .label_syms = syms_new(), + + .in_typedef = false, + }; + return r; +} + +void resolver_free(Resolver* r) +{ + syms_free(r->ord_syms); + syms_free(r->tag_syms); + syms_free(r->label_syms); + free(r); +} + +static AstVisitorResult visit_stmt_block(AstVisitor* v, AstStmtBlock* node) +{ + Resolver* r = v->op; + syms_push_scope(r->ord_syms); + + ast_stmt_block_visit_body(v, node); + + syms_pop_scope(r->ord_syms); + return AstVisitor_Break; +} + +static AstVisitorResult visit_stmt(AstVisitor* v, AstStmt* node) +{ +} + +static AstVisitorResult visit_decl(AstVisitor* v, AstDecl* node) +{ + Resolver* r = v->op; +} + +static AstVisitorResult visit_declar(AstVisitor* v, AstDeclar* node) +{ + Resolver* r = v->op; + if (node->ty == AstDeclar_Function) { + syms_push_scope(r->ord_syms); + + ast_declar_visit_body(v, node); + + syms_pop_scope(r->ord_syms); + return AstVisitor_Break; + } + + if (node->ty == AstDeclar_Ident) { } +} + +static AstVisitorResult visit_expr(AstVisitor* v, AstExpr* node) +{ +} + +void resolver_resolve_top_stmt(Resolver* r, AstStmt* stmt) +{ + if (stmt->ty != AstStmt_Decl) { + fprintf( + stderr, "error: expected declaration on line %d\n", stmt->loc.line); + exit(1); + } + + AstVisitor v = { + .visit_stmt_block = visit_stmt_block, + .visit_stmt = visit_stmt, + .visit_decl = visit_decl, + .visit_declar = visit_declar, + .visit_expr = visit_expr, + .op = r, + }; + + visit_stmt(&v, stmt); +} diff --git a/resolve.h b/resolve.h new file mode 100644 index 0000000..be606ef --- /dev/null +++ b/resolve.h @@ -0,0 +1,13 @@ +#ifndef RES_H +#define RES_H + +#include "ast.h" + +typedef struct Resolver Resolver; + +Resolver* resolver_new(); +void resolver_free(Resolver* r); + +void resolver_resolve_top_stmt(Resolver* r, AstStmt* stmt); + +#endif