#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; } }