/** * @file parser.c * @brief 新的解析器实现 */ #include "parser.h" #include static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type, void *node) { (void)context; (void)node_type; (void)node; return; } #define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \ assigned_val = value ? value : default void scc_parser_init(scc_parser_t *parser, scc_lexer_stream_t *lexer, scc_sema_callbacks_t *callbacks) { Assert(parser != null && lexer != null); parser->lex_stream = lexer; parser->has_error = false; parser->translation_unit = null; if (callbacks) { ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_decl, callbacks->on_decl, dummy_sema_callback); ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_stmt, callbacks->on_stmt, dummy_sema_callback); ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_expr, callbacks->on_expr, dummy_sema_callback); ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_type, callbacks->on_type, dummy_sema_callback); parser->sema_callbacks.context = callbacks->context; } else { parser->sema_callbacks.on_decl = dummy_sema_callback; parser->sema_callbacks.on_stmt = dummy_sema_callback; parser->sema_callbacks.on_expr = dummy_sema_callback; parser->sema_callbacks.on_type = dummy_sema_callback; parser->sema_callbacks.context = dummy_sema_callback; } // // ONLY FOR INIT TYPE // parser->current_token.type = SCC_TOK_UNKNOWN; } void scc_parser_drop(scc_parser_t *parser) { // TODO: 释放 AST 内存 (void)parser; } 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 null; unit->base.type = SCC_AST_TRANSLATION_UNIT; scc_vec_init(unit->declarations); /** * Program := (Declaration | Definition)* * same as * Program := Declaration* Definition* */ do { scc_ast_decl_t *decl = scc_parse_declaration(parser); if (decl != null) { scc_vec_push(unit->declarations, decl); } else { break; // MAYBE return or next } } while (!scc_lexer_tok_match(scc_lexer_stream_current(parser->lex_stream), SCC_TOK_EOF) && !parser->has_error); if (parser->has_error) { // TODO: 清理 scc_free(unit); return null; } Assert(unit->base.type == SCC_AST_TRANSLATION_UNIT); return unit; }