#include #include static void dummy_sema_callback(scc_sema_ctx_t *context, scc_ast_node_kind_t node_type, void *node) { (void)context; (void)node_type; (void)node; return; } static const scc_ast_qual_type_t * dummy_got_type_callback(scc_sema_ctx_t *context, const char *name) { (void)context; (void)name; return nullptr; } #define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \ assigned_val = value ? value : default void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring, scc_ast_ctx_t *ast_ctx, scc_sema_ctx_t *sema_ctx) { Assert(parser != nullptr && tok_ring != nullptr); Assert(ast_ctx != nullptr); parser->ast_ctx = ast_ctx; parser->ring = tok_ring; parser->errcode = 0; parser->translation_unit = nullptr; if (sema_ctx == nullptr) { parser->sema_ctx = scc_malloc(sizeof(scc_sema_ctx_t)); Assert(parser->sema_ctx != nullptr); parser->sema_ctx->on_decl = dummy_sema_callback; parser->sema_ctx->on_stmt = dummy_sema_callback; parser->sema_ctx->on_expr = dummy_sema_callback; parser->sema_ctx->on_type = dummy_sema_callback; parser->sema_ctx->got_type = dummy_got_type_callback; parser->sema_ctx->context = nullptr; parser->owned_sema = true; } else { parser->owned_sema = false; parser->sema_ctx = sema_ctx; } } void scc_parser_drop(scc_parser_t *parser) { // TODO: 释放 AST 内存 scc_ring_free(*parser->ring); if (parser->owned_sema) { scc_free(parser->sema_ctx); } else { scc_sema_drop(parser->sema_ctx); } } scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) { scc_ast_translation_unit_t *unit = scc_malloc(sizeof(scc_ast_translation_unit_t)); if (!unit) return nullptr; unit->base.type = SCC_AST_TRANSLATION_UNIT; scc_vec_init(unit->declarations); /** * Program := (Declaration | Definition)* * same as * Program := Declaration* Definition* */ while (1) { scc_ast_decl_t *decl = scc_parse_declaration(parser); if (decl != nullptr) { scc_vec_push(unit->declarations, decl); } else { break; } if (parser->errcode != 0) { // FIXME errcode SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d", parser->errcode); break; } const scc_lexer_tok_t *tok = scc_parser_peek(parser); if (tok == nullptr || tok->type == SCC_TOK_EOF) { break; } } if (parser->errcode) { // TODO: 清理 SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d", parser->errcode); scc_free(unit); return nullptr; } Assert(unit->base.type == SCC_AST_TRANSLATION_UNIT); return unit; }