diff --git a/Makefile b/Makefile index 26816aa..ba421de 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -larpcc: main.c lex.c preproc.c collection.c parse.c syms.c ast_str.c +larpcc: main.c lex.c preproc.c collection.c parse.c syms.c ast_print.c resolve.c gcc $^ -o $@ -std=c23 -pedantic -Wall -Wextra -g -fsanitize=address -Werror=switch diff --git a/ast.h b/ast.h index 08f525f..175ce6f 100644 --- a/ast.h +++ b/ast.h @@ -2,6 +2,7 @@ #define AST_H #include "collection.h" +#include typedef struct { int line; @@ -92,6 +93,7 @@ struct AstDeclar { }; typedef enum { + AstExpr_Ident, AstExpr_Str, AstExpr_Call, } AstExprTy; @@ -100,6 +102,7 @@ struct AstExpr { AstExprTy ty; Loc loc; union { + char* ident; char* str_val; struct { AstExpr* expr; @@ -108,17 +111,37 @@ struct AstExpr { }; }; -typedef struct { - ARRAY_FIELD(char, string); - Arena* arena; - int depth; -} AstStringifier; +void ast_stmt_block_print(FILE* f, const AstStmtBlock* node, int depth); +void ast_stmt_print(FILE* f, const AstStmt* node, int depth); +void ast_decl_print(FILE* f, const AstDecl* node, int depth); +void ast_declar_print(FILE* f, const AstDeclar* node, int depth); +void ast_expr_print(FILE* f, const AstExpr* node, int depth); -void ast_stringifier_init(AstStringifier* s, Arena* arena); -void ast_stmt_block_to_string(AstStringifier* s, const AstStmtBlock* node); -void ast_stmt_to_string(AstStringifier* s, const AstStmt* node); -void ast_decl_to_string(AstStringifier* s, const AstDecl* node); -void ast_declar_to_string(AstStringifier* s, const AstDeclar* node); -void ast_expr_to_string(AstStringifier* s, const AstExpr* node); +typedef struct AstVisitor AstVisitor; + +typedef enum { + AstVisitor_Continue, + AstVisitor_Break, +} AstVisitorResult; + +struct AstVisitor { + AstVisitorResult (*visit_stmt_block)(AstVisitor* v, AstStmtBlock* node); + AstVisitorResult (*visit_stmt)(AstVisitor* v, AstStmt* node); + AstVisitorResult (*visit_decl)(AstVisitor* v, AstDecl* node); + AstVisitorResult (*visit_declar)(AstVisitor* v, AstDeclar* node); + AstVisitorResult (*visit_expr)(AstVisitor* v, AstExpr* node); + void* op; +}; + +void ast_stmt_block_visit(AstVisitor* v, AstStmtBlock* node); +void ast_stmt_block_visit_body(AstVisitor* v, AstStmtBlock* node); +void ast_stmt_visit(AstVisitor* v, AstStmt* node); +void ast_stmt_visit_body(AstVisitor* v, AstStmt* node); +void ast_decl_visit(AstVisitor* v, AstDecl* node); +void ast_decl_visit_body(AstVisitor* v, AstDecl* node); +void ast_declar_visit(AstVisitor* v, AstDeclar* node); +void ast_declar_visit_body(AstVisitor* v, AstDeclar* node); +void ast_expr_visit(AstVisitor* v, AstExpr* node); +void ast_expr_visit_body(AstVisitor* v, AstExpr* node); #endif 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/ast_str.c b/ast_str.c deleted file mode 100644 index 0feca1e..0000000 --- a/ast_str.c +++ /dev/null @@ -1,283 +0,0 @@ -#include "ast.h" -#include "collection.h" -#include -#include -#include - -static void push(AstStringifier* s, const char* str) -{ - for (; *str; ++str) { - arena_array_push(s->arena, - (void**)&s->string, - &s->string_cap, - &s->string_size, - (void*)str, - sizeof(*str)); - } - - char ch = '\0'; - arena_array_push(s->arena, - (void**)&s->string, - &s->string_cap, - &s->string_size, - (void*)&ch, - sizeof(ch)); - s->string_size -= 1; -} - -#define pushf(S, ...) \ - do { \ - size_t len = snprintf(nullptr, 0, __VA_ARGS__); \ - char* buf = calloc(len + 1, 1); \ - snprintf(buf, len + 1, __VA_ARGS__); \ - push(S, buf); \ - free(buf); \ - } while (false) - -static void indent(AstStringifier* s) -{ - for (int i = 0; i < s->depth; ++i) { - push(s, " "); - } -} - -void ast_stringifier_init(AstStringifier* s, Arena* arena) -{ - *s = (AstStringifier) { - ARRAY_FIELD_INIT(string), - .arena = arena, - .depth = 0, - }; -} - -void ast_stmt_block_to_string(AstStringifier* s, const AstStmtBlock* node) -{ - pushf(s, "StmtBlock %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - indent(s); - push(s, "stmts: ["); - - if (node->stmts_size) { - s->depth += 1; - push(s, "\n"); - for (size_t i = 0; i < node->stmts_size; ++i) { - indent(s); - ast_stmt_to_string(s, node->stmts[i]); - push(s, ",\n"); - } - s->depth -= 1; - indent(s); - } - push(s, "],"); - - s->depth -= 1; - indent(s); - push(s, "}"); -} - -void ast_stmt_to_string(AstStringifier* s, const AstStmt* node) -{ - switch (node->ty) { - case AstStmt_Decl: { - pushf(s, "Stmt::Decl %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - push(s, "decl: "); - ast_decl_to_string(s, node->decl); - push(s, ",\n"); - - s->depth -= 1; - indent(s); - push(s, "}"); - break; - } - case AstStmt_Expr: { - pushf(s, "Stmt::Expr %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - indent(s); - - push(s, "expr: "); - - ast_expr_to_string(s, node->expr); - push(s, ",\n"); - - s->depth -= 1; - indent(s); - push(s, "}"); - break; - } - } -} - -static void spec_to_string(AstStringifier* s, 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) - push(s, " "); - first = false; - push(s, spec_idents[i].ident); - } - } -} - -void ast_decl_to_string(AstStringifier* s, const AstDecl* node) -{ - pushf(s, "Decl %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - push(s, "spec: ["); - spec_to_string(s, node->spec); - push(s, "],\n"); - - if (node->spec & AstSpec_DefTy) { - assert(node->type_ident); - indent(s); - pushf(s, "type_ident: \"%s\",\n", node->type_ident); - } - - indent(s); - push(s, "declars: ["); - if (node->declars_size) { - push(s, "\n"); - s->depth += 1; - - for (size_t i = 0; i < node->declars_size; ++i) { - indent(s); - ast_declar_to_string(s, node->declars[i]); - push(s, ",\n"); - } - - s->depth -= 1; - indent(s); - push(s, "],\n"); - } else { - push(s, "],\n"); - } - - if (node->function_body) { - indent(s); - push(s, "function_body: "); - ast_stmt_block_to_string(s, node->function_body); - push(s, ",\n"); - } - - s->depth -= 1; - indent(s); - push(s, "}"); -} - -void ast_declar_to_string(AstStringifier* s, const AstDeclar* node) -{ - switch (node->ty) { - case AstDeclar_Ident: { - pushf(s, "Declar::Ident %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - pushf(s, "ident: \"%s\",\n", node->ident); - - break; - } - case AstDeclar_Pointer: { - pushf( - s, "Declar::Pointer %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - push(s, "declar: "); - ast_declar_to_string(s, node->pointer.declar); - push(s, ",\n"); - - indent(s); - push(s, "spec: ["); - spec_to_string(s, node->pointer.spec); - push(s, "],\n"); - - break; - } - case AstDeclar_Array: { - pushf(s, "Declar::Array %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - push(s, "declar: "); - ast_declar_to_string(s, node->array.declar); - push(s, ",\n"); - - indent(s); - push(s, "expr: "); - ast_expr_to_string(s, node->array.expr); - push(s, ",\n"); - - break; - } - case AstDeclar_Function: { - pushf( - s, "Declar::Function %d:%d {\n", node->loc.line, node->loc.col); - s->depth += 1; - - indent(s); - push(s, "declar: "); - ast_declar_to_string(s, node->array.declar); - push(s, ",\n"); - - indent(s); - push(s, "params: ["); - if (node->function.params_size) { - push(s, "\n"); - s->depth += 1; - - for (size_t i = 0; i < node->function.params_size; ++i) { - indent(s); - ast_decl_to_string(s, node->function.params[i]); - push(s, ",\n"); - } - - s->depth -= 1; - indent(s); - push(s, "],\n"); - } else { - push(s, "],\n"); - } - - break; - } - } - - if (node->init_expr) { - indent(s); - push(s, "decl: "); - ast_expr_to_string(s, node->init_expr); - push(s, ",\n"); - } - - s->depth -= 1; - indent(s); - push(s, "}"); -} - -void ast_expr_to_string(AstStringifier* s, const AstExpr* node) -{ - push(s, ""); -} diff --git a/main.c b/main.c index a6cfaa8..eae82f3 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ #include "ast.h" #include "collection.h" #include "parse.h" +#include "resolve.h" #include #include #include @@ -77,22 +78,19 @@ int main(int argc, char* argv[]) Parser* parser = parser_new(&tokstream, &ast_arena); + Resolver* resolver = resolver_new(); + AstStmt* stmt; while (!parser_done(parser)) { stmt = parser_parse_stmt(parser); - Arena s_arena; - arena_init(&s_arena, 4096); - AstStringifier s = { }; - ast_stringifier_init(&s, &s_arena); + ast_stmt_print(stdout, stmt, 0); - ast_stmt_to_string(&s, stmt); - - printf("%s\n", s.string); - - arena_deinit(&s_arena); + printf("\n"); } + resolver_free(resolver); + parser_free(parser); preproc_free(preproc); diff --git a/parse.c b/parse.c index 0034254..bb7519e 100644 --- a/parse.c +++ b/parse.c @@ -25,21 +25,6 @@ typedef struct { ARRAY_FIELD(KwNode, nodes); } KwMatcher; -static void kw_tree_print(KwMatcher* m, KwNode* node, int depth) -{ - for (size_t i = 0; i < node->opts_size; ++i) { - for (int i = 0; i < depth; ++i) - printf(" "); - printf("%c", node->opts[i].ch); - if (node->opts[i].is_term) { - printf(" = %s\n", tokty_str(node->opts[i].val)); - } else { - printf("\n"); - kw_tree_print(m, &m->nodes[node->opts[i].val], depth + 1); - } - } -} - static KwNodeOpt* kwmatcher_create_path( KwMatcher* m, size_t node_idx, const char* kw) { @@ -60,12 +45,7 @@ static KwNodeOpt* kwmatcher_create_path( ARRAY_FIELD_INIT(opts), .idx = new_idx, }; - arena_array_push(&m->arena, - (void**)&m->nodes, - &m->nodes_cap, - &m->nodes_size, - &new_node, - sizeof(new_node)); + ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, &new_node); // might have been relocated node = &m->nodes[node_idx]; @@ -74,12 +54,7 @@ static KwNodeOpt* kwmatcher_create_path( .is_term = false, .val = new_idx, }; - arena_array_push(&m->arena, - (void**)&node->opts, - &node->opts_cap, - &node->opts_size, - &new_opt, - sizeof(new_opt)); + ARENA_ARRAY_FIELD_PUSH(&m->arena, node, opts, &new_opt); opt = &node->opts[node->opts_size - 1]; } @@ -131,12 +106,7 @@ static void kwmatcher_init(KwMatcher* m, TokStream* tokstream) arena_init(&m->arena, 512); - arena_array_push(&m->arena, - (void**)&(m)->nodes, - &(m)->nodes_cap, - &(m)->nodes_size, - (&(KwNode) { .idx = 0 }), - sizeof(*(&(KwNode) { .idx = 0 }))); + ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, (&(KwNode) { .idx = 0 })); struct { TokTy ty; @@ -150,8 +120,6 @@ static void kwmatcher_init(KwMatcher* m, TokStream* tokstream) for (size_t i = 0; i < sizeof(kws) / sizeof(kws[0]); ++i) { kwmatcher_add(m, kws[i].kw, kws[i].ty); } - - kw_tree_print(m, &m->nodes[0], 0); } static void kwmatcher_deinit(KwMatcher* m) @@ -165,12 +133,10 @@ static Tok kwmatcher_next(KwMatcher* m) if (tok.ty != Tok_Ident) goto exit; TokTy ty = kwmatcher_match(m, tok.text); - if (ty != Tok_Ident) - printf("info: matched '%s' on line %d\n", tok.text, tok.loc.line); tok.ty = ty; exit: - printf(" - %s(%s) %d:%d\n", + printf(" - %-10s %-10s %d:%d\n", tokty_str(tok.ty), tok.text, tok.loc.line, @@ -178,16 +144,20 @@ exit: return tok; } +typedef enum : unsigned int { + ParserFlags_ParsingTypedef = 1 << 0, +} ParserFlags; + struct Parser { KwMatcher kwmatcher; Arena* arena; Arena sym_arena; - Syms* ord_ns; - Syms* label_ns; - Syms* tag_ns; + Syms* syms; Tok curr; + + ParserFlags flags; }; Parser* parser_new(TokStream* tokstream, Arena* arena) @@ -199,11 +169,11 @@ Parser* parser_new(TokStream* tokstream, Arena* arena) .arena = arena, .sym_arena = { }, - .ord_ns = syms_new(), - .label_ns = syms_new(), - .tag_ns = syms_new(), + .syms = syms_new(), .curr = { }, + + .flags = 0, }; kwmatcher_init(&p->kwmatcher, tokstream); @@ -215,6 +185,7 @@ Parser* parser_new(TokStream* tokstream, Arena* arena) void parser_free(Parser* p) { kwmatcher_deinit(&p->kwmatcher); + syms_free(p->syms); free(p); } @@ -239,7 +210,8 @@ DEFINE_NEW(AstExpr, expr) DEFINE_NEW(AstStmtBlock, stmt_block) static AstStmtBlock* parse_stmt_block(Parser* p); -static AstDecl* parse_decl(Parser* p); +static AstStmt* parse_stmt(Parser* p); +static AstDecl* parse_decl(Parser* p, bool is_param); static AstDeclar* parse_declar(Parser* p); static AstSpec parse_decl_spec(Parser* p); static AstExpr* parse_expr(Parser* p); @@ -248,17 +220,13 @@ static AstStmtBlock* parse_stmt_block(Parser* p) { Loc loc = p->curr.loc; assert(p->curr.ty == '{'); + step(p); ARRAY_VAR(AstStmt*, stmts); while (p->curr.ty != Tok_Eof && p->curr.ty != '}') { - AstStmt* stmt = parser_parse_stmt(p); - arena_array_push(p->arena, - (void**)&stmts, - &stmts_cap, - &stmts_size, - (&stmt), - sizeof(*(&stmt))); + AstStmt* stmt = parse_stmt(p); + ARENA_ARRAY_VAR_PUSH(p->arena, stmts, &stmt); } if (p->curr.ty != '}') { @@ -292,7 +260,7 @@ static bool is_defty_ident(Parser* p, Tok tok) { if (tok.ty != Tok_Ident) return false; - Sym* sym = syms_get(p->ord_ns, tok.text); + Sym* sym = syms_get(p->syms, tok.text); return sym && sym->ty == Sym_Typedef; } @@ -301,7 +269,7 @@ static AstStmt* parse_stmt(Parser* p) Loc loc = p->curr.loc; if (is_decl_start_kw(p->curr.ty) || is_defty_ident(p, p->curr)) { - AstDecl* decl = parse_decl(p); + AstDecl* decl = parse_decl(p, false); if (!decl->function_body && p->curr.ty != ';') { fprintf( @@ -320,6 +288,12 @@ static AstStmt* parse_stmt(Parser* p) AstExpr* expr = parse_expr(p); + if (p->curr.ty != ';') { + fprintf(stderr, "error: expected ';' on line %d\n", p->curr.loc.line); + exit(1); + } + step(p); + return new_stmt(p, (AstStmt) { .ty = AstStmt_Expr, @@ -328,50 +302,47 @@ static AstStmt* parse_stmt(Parser* p) }); } -static AstDecl* parse_decl(Parser* p) +static AstDecl* parse_decl(Parser* p, bool is_param) { Loc loc = p->curr.loc; AstSpec spec = parse_decl_spec(p); + if (spec & AstSpec_Typedef) { + p->flags |= ParserFlags_ParsingTypedef; + } + ARRAY_VAR(AstDeclar*, declars); AstDeclar* first = parse_declar(p); ARENA_ARRAY_VAR_PUSH(p->arena, declars, &first); - if (first->ty == AstDeclar_Function && p->curr.ty == '{') { - AstStmtBlock* block = parse_stmt_block(p); - return new_decl(p, - (AstDecl) { - .spec = spec, - .declars = declars, - .declars_cap = declars_cap, - .declars_size = declars_size, - .function_body = block, - .loc = loc, - }); + AstStmtBlock* function_body = nullptr; + bool multi_allowed = !is_param; + + if (!is_param && first->ty == AstDeclar_Function && p->curr.ty == '{') { + function_body = parse_stmt_block(p); + multi_allowed = false; } - while (p->curr.ty == ',') { + while (multi_allowed && p->curr.ty == ',') { step(p); AstDeclar* declar = parse_declar(p); - array_push((void**)&declars, - &declars_cap, - &declars_size, - (&declar), - sizeof(*(&declar))); + ARENA_ARRAY_VAR_PUSH(p->arena, declars, &declar); } + p->flags &= ~ParserFlags_ParsingTypedef; + return new_decl(p, (AstDecl) { .spec = spec, .declars = declars, .declars_cap = declars_cap, .declars_size = declars_size, - .function_body = nullptr, + .function_body = function_body, .loc = loc, }); } @@ -461,13 +432,16 @@ static AstDeclar* parse_declar_l3(Parser* p) ARRAY_VAR(AstDecl*, params); - while (true) { - AstDecl* d = parse_decl(p); + if (p->curr.ty != Tok_Eof && p->curr.ty != ')') { + AstDecl* d = parse_decl(p, true); ARENA_ARRAY_VAR_PUSH(p->arena, params, &d); - if (p->curr.ty != ',') - break; - step(p); + while (p->curr.ty == ',') { + step(p); + + d = parse_decl(p, true); + ARENA_ARRAY_VAR_PUSH(p->arena, params, &d); + } } if (p->curr.ty != ')') { @@ -502,7 +476,7 @@ static AstDeclar* parse_declar_l4(Parser* p) step(p); return new_declar(p, (AstDeclar) { - .ty = AstDeclar_Array, + .ty = AstDeclar_Ident, .loc = loc, .ident = ident, }); @@ -535,7 +509,7 @@ static AstSpec parse_decl_spec(Parser* p) while (true) { switch (p->curr.ty) { case Tok_Ident: { - Sym* sym = syms_get(p->ord_ns, p->curr.text); + Sym* sym = syms_get(p->syms, p->curr.text); if (!sym || sym->ty != Sym_Typedef) break; spec |= AstSpec_DefTy; @@ -580,7 +554,6 @@ static AstExpr* parse_expr_1(Parser* p) while (true) { if (p->curr.ty == '(') { - step(p); ARRAY_VAR(AstExpr*, args); @@ -588,7 +561,7 @@ static AstExpr* parse_expr_1(Parser* p) do { step(p); AstExpr* arg = parse_expr(p); - ARRAY_VAR_PUSH(args, &arg); + ARENA_ARRAY_VAR_PUSH(p->arena, args, &arg); } while (p->curr.ty == ','); } @@ -626,7 +599,7 @@ static size_t unescape_string(char* dest, const char* src) assert(src[0] == '"' && src[src_len - 1] == '"'); - src -= 1; + src += 1; src_len -= 2; for (size_t i = 0; i < src_len; ++i) { @@ -663,6 +636,8 @@ static size_t unescape_string(char* dest, const char* src) dest_i += 1; } + if (dest) + dest[dest_i] = '\0'; return dest_i; } @@ -670,6 +645,17 @@ static AstExpr* parse_expr_2(Parser* p) { Loc loc = p->curr.loc; + if (p->curr.ty == Tok_Ident) { + char* ident = arena_strdup(p->arena, p->curr.text); + step(p); + return new_expr(p, + (AstExpr) { + .ty = AstExpr_Ident, + .loc = loc, + .ident = ident, + }); + } + if (p->curr.ty == Tok_Str) { size_t unescaped_len = unescape_string(nullptr, p->curr.text); char* unescaped_str = arena_alloc(p->arena, unescaped_len + 1); 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 diff --git a/syms.c b/syms.c index 6ea8b91..5596f20 100644 --- a/syms.c +++ b/syms.c @@ -22,6 +22,7 @@ Syms* syms_new() void syms_free(Syms* s) { + free(s->maps); free(s); }