diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index eb34884..e89d7f0 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -189,7 +189,7 @@ struct scc_ast_type { } enumeration; struct { const char *name; - scc_ast_type_t *underlying; + scc_ast_decl_t *decl; } typedef_type; }; }; diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index f1c07ed..6320bd3 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -341,10 +341,33 @@ static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr, _scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member); } -// TODO -// SCC_AST_EXPR_CAST, // 类型转换 -// SCC_AST_EXPR_SIZE_OF, // sizeof -// SCC_AST_EXPR_ALIGN_OF, // _Alignof +static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr, + scc_ast_type_t *type, + scc_ast_expr_t *operand) { + Assert(expr != null && type != null && operand != null); + expr->base.loc = scc_pos_create(); + expr->base.type = SCC_AST_EXPR_CAST; + expr->cast.type = type; + expr->cast.expr = operand; +} + +static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr, + scc_ast_type_t *type) { + Assert(expr != null && type != null); + expr->base.loc = scc_pos_create(); + expr->base.type = SCC_AST_EXPR_SIZE_OF; + expr->attr_of.type = type; + expr->attr_of.expr = null; +} + +static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr, + scc_ast_type_t *type) { + Assert(expr != null && type != null); + expr->base.loc = scc_pos_create(); + expr->base.type = SCC_AST_EXPR_SIZE_OF; + expr->attr_of.type = type; + expr->attr_of.expr = null; +} // init can be null static inline void @@ -486,18 +509,18 @@ static inline void scc_ast_type_enum_init(scc_ast_type_t *type, type->base.type = SCC_AST_TYPE_ENUM; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->enumeration.name = name; - type->enumeration.decl = null; + type->enumeration.decl = decl; } static inline void scc_ast_type_typedef_init(scc_ast_type_t *type, const char *name, - scc_ast_type_t *target) { + scc_ast_decl_t *target) { Assert(type != null && target != null); type->base.loc = scc_pos_create(); type->base.type = SCC_AST_TYPE_TYPEDEF; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->typedef_type.name = name; - type->typedef_type.underlying = target; + type->typedef_type.decl = target; } #endif /* __SCC_AST_H__ */ diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index c834c13..3840f1d 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -567,6 +567,10 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) { dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true); break; + case SCC_AST_STMT_BREAK: + case SCC_AST_STMT_CONTINUE: + break; + case SCC_AST_STMT_DEFAULT: end_node_dump(ctx); dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true); diff --git a/libs/parser/include/parser_utils.h b/libs/parser/include/parser_utils.h index 9ad92ee..05d3269 100644 --- a/libs/parser/include/parser_utils.h +++ b/libs/parser/include/parser_utils.h @@ -71,4 +71,13 @@ static inline void scc_parser_reset(scc_parser_t *parser) { scc_ring_reset(*parser->ring); } +#include +static inline scc_pos_t scc_parser_got_current_pos(scc_parser_t *parser) { + const scc_lexer_tok_t *tok = scc_parser_peek(parser); + scc_pos_t pos = scc_pos_create(); + if (tok != null) + pos = tok->loc; + return pos; +} + #endif /* __SCC_PARSER_UTILS_H__ */ diff --git a/libs/parser/include/scc_parser.h b/libs/parser/include/scc_parser.h index 9e702a4..aa84554 100644 --- a/libs/parser/include/scc_parser.h +++ b/libs/parser/include/scc_parser.h @@ -58,6 +58,8 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser); * @return 语句 AST 节点 */ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser); +scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser); +scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser); /** * @brief 解析表达式 @@ -75,4 +77,24 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser); scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser); +static inline void scc_parse_decl_sema(scc_parser_t *parser, + scc_ast_decl_t *decl) { + parser->sema_callbacks.on_decl(parser->sema_callbacks.context, + decl ? decl->base.type : SCC_AST_UNKNOWN, + decl); +} + +static inline void scc_parse_type_sema(scc_parser_t *parser, + scc_ast_type_t *type) { + parser->sema_callbacks.on_type(parser->sema_callbacks.context, + type ? type->base.type : SCC_AST_UNKNOWN, + type); +} + +static inline scc_ast_type_t *scc_parse_got_type(scc_parser_t *parser, + const char *name) { + return parser->sema_callbacks.got_type(parser->sema_callbacks.context, + name); +} + #endif /* __SCC_PARSER_H__ */ diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index b1123d9..0944b84 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -155,9 +155,6 @@ A.2.4 External definitions #include scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { - cbool ok; - scc_lexer_tok_t tok; - scc_ast_node_t *type_or_decl = _scc_parse_type(parser); scc_ast_decl_t *decl = null; if (type_or_decl == null) { @@ -182,7 +179,7 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { } else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) { decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl); } else { - LOG_ERROR("invalid declaration"); + SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration"); return null; } @@ -195,7 +192,7 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { scc_ast_expr_t *init = scc_parse_expression(parser); decl->var.init = init; if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("expect semicolon"); + SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon"); } goto RETURN; } else if (tok_ptr->type == SCC_TOK_L_BRACE) { @@ -211,9 +208,6 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { } RETURN: - if (decl) { - parser->sema_callbacks.on_decl(parser->sema_callbacks.context, - decl->base.type, decl); - } + scc_parse_decl_sema(parser, decl); return decl; } diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 2a7d440..14573e3 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -167,8 +167,6 @@ static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser); // 特殊结构:独立解析(右结合、条件、一元、后缀、基本) static scc_ast_expr_t * -parse_assignment_expression(scc_parser_t *parser); // 右结合 -static scc_ast_expr_t * parse_conditional_expression(scc_parser_t *parser); // 右结合 static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser); // 类型转换 static scc_ast_expr_t * @@ -520,7 +518,7 @@ static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser) { } // 赋值表达式(右结合) -static scc_ast_expr_t *parse_assignment_expression(scc_parser_t *parser) { +scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { // 先解析左侧的 unary-expression(C 标准规定赋值左边必须是 // unary-expression) scc_ast_expr_t *left = null; @@ -542,7 +540,7 @@ static scc_ast_expr_t *parse_assignment_expression(scc_parser_t *parser) { scc_lexer_tok_drop(&op_tok); // 解析右侧(右结合:继续调用 parse_assignment_expression) - scc_ast_expr_t *right = parse_assignment_expression(parser); + scc_ast_expr_t *right = scc_parse_assignment_expression(parser); if (!right) { // 错误恢复 parser_sync(parser); @@ -577,7 +575,8 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { // 消耗 ':' if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) { - LOG_ERROR("Expected ':' after '?'"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ':' after '?'"); parser_sync(parser); return null; } @@ -600,6 +599,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { if (tok && tok->type == SCC_TOK_L_PAREN) { // 尝试解析类型名 scc_parser_store(parser); + scc_parser_next(parser); scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现 if (type) { // 消耗了类型名后,下一个应该是 ')' @@ -618,13 +618,12 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { return expr; } else { // 不是类型转换,回退 - scc_parser_restore(parser); // 释放 type(假设 scc_parse_type_name 分配了) // TODO: scc_ast_type_drop(type); } } else { - // 解析类型名失败,回退 scc_parser_restore(parser); + // 解析类型名失败,回退 } } // 否则作为一元表达式 @@ -679,7 +678,8 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { const scc_lexer_tok_t *next = scc_parser_peek(parser); if (!next) { - LOG_ERROR("Unexpected end after sizeof"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Unexpected end after sizeof"); return null; } @@ -741,7 +741,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { return null; } if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) { - LOG_ERROR("Expected ']' after subscript"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ']' after subscript"); parser_sync(parser); return null; } @@ -766,7 +767,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { // 解析参数列表 if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { while (1) { - scc_ast_expr_t *arg = parse_assignment_expression(parser); + scc_ast_expr_t *arg = + scc_parse_assignment_expression(parser); if (!arg) { parser_sync(parser); // 释放已解析的参数 @@ -781,7 +783,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { break; } else { - LOG_ERROR("Expected ',' or ')' in function call"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ',' or ')' in function call"); parser_sync(parser); // 释放资源 scc_free(call); @@ -800,12 +803,14 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_lexer_tok_t ident_tok; if (!scc_parser_next_consume(parser, &ident_tok) || ident_tok.type != SCC_TOK_IDENT) { - LOG_ERROR("Expected identifier after member access"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected identifier after member access"); scc_lexer_tok_drop(&op_tok); parser_sync(parser); return null; } const char *name = scc_cstring_as_cstr(&ident_tok.lexeme); + scc_ast_expr_t *member = expr_create( parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER : SCC_AST_EXPR_PTR_MEMBER); @@ -944,7 +949,8 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) { } if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("Expected ')' after expression"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ')' after expression"); parser_sync(parser); return null; } @@ -952,12 +958,12 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) { } scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { - scc_ast_expr_t *left = parse_assignment_expression(parser); + scc_ast_expr_t *left = scc_parse_assignment_expression(parser); if (!left) return null; while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) { - scc_ast_expr_t *right = parse_assignment_expression(parser); + scc_ast_expr_t *right = scc_parse_assignment_expression(parser); if (!right) { parser_sync(parser); return null; @@ -966,3 +972,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { } return left; } + +scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) { + return parse_conditional_expression(parser); +} diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 52976ec..9ecdf43 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -49,6 +49,7 @@ A.2.3 Statements #include #include + static inline scc_ast_stmt_t *ast_stmt_alloc() { scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t)); if (stmt == null) { @@ -59,13 +60,15 @@ static inline scc_ast_stmt_t *ast_stmt_alloc() { static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) { if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { - LOG_ERROR("Expected '(' before like `( expression )` ."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected '(' before like `( expression )` ."); } scc_ast_expr_t *ret = scc_parse_expression(parser); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("Expected ')' before like `( expression )` ."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ')' before like `( expression )` ."); } return ret; } @@ -97,10 +100,16 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) { } scc_ast_expr_t *expr = null; - // TODO = scc_parser_constant_expression(); + expr = scc_parser_constant_expression(parser); + if (expr == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected constant expression after case."); + return null; + } if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) { - LOG_ERROR("Expected constant expression after case."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected `:` after case."); return null; } @@ -120,7 +129,8 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) { } if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) { - LOG_ERROR("Expected constant expression after case."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected constant expression after case."); return null; } @@ -150,7 +160,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) { ret = (scc_ast_node_t *)scc_parse_statement(parser); } if (ret == null) { - LOG_ERROR("Invalid statement"); + SCC_ERROR(scc_parser_got_current_pos(parser), "Invalid statement"); // TODO free parser->errcode = 1; return null; @@ -217,7 +227,8 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) { scc_ast_stmt_t *statement = scc_parse_statement(parser); if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) { - LOG_ERROR("Expected 'while' after do."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected 'while' after do."); // TODO 使用更好的错误处理,未来应当采用更好的内存管理器 scc_free(statement); return null; @@ -240,7 +251,8 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) { */ if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { - LOG_ERROR("Expected '(' before like `( expression )` ."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected '(' before like `( expression )` ."); } scc_ast_type_t *init = null; @@ -253,20 +265,23 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) { if (init == null) { init = (scc_ast_type_t *)scc_parse_expression(parser); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("Expected semicolon in for statement."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected semicolon in for statement."); } } cond = scc_parse_expression(parser); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("Expected semicolon in for statement."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected semicolon in for statement."); } incr = scc_parse_expression(parser); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("Expected ')' after like `( expression )` ."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ')' after like `( expression )` ."); } body = scc_parse_statement(parser); @@ -284,7 +299,8 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) { if (scc_parser_next_consume(parser, &tok)) { scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme)); } else { - LOG_ERROR("Expected label after goto."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected label after goto."); } } else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) { scc_ast_stmt_continue_init(stmt); @@ -297,7 +313,8 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) { } if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("Expected semicolon after jump statement."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected semicolon after jump statement."); } return stmt; } @@ -319,7 +336,8 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) { scc_ast_stmt_expr_init(stmt, expr); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("Expected semicolon after expression."); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected semicolon after expression."); } return stmt; } diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index b560a95..098f8ab 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -212,15 +212,10 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) { // 函数说明符 case SCC_TOK_INLINE: return true; - - // typedef 名称(标识符也可能是类型说明符) + // typedef 名称(标识符也可能是类型说明符) case SCC_TOK_IDENT: - // 需要检查标识符是否在符号表中定义为 typedef - // 这里简化处理:假设所有标识符都可能是 typedef - // 在实际解析器中,需要查询符号表 - // TODO - return false; - + return scc_parse_got_type( + parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null; default: return false; } @@ -250,7 +245,8 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) { // typedef 名称 case SCC_TOK_IDENT: // 需要检查标识符是否在符号表中定义为 typedef - return true; + return scc_parse_got_type( + parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null; default: return false; } @@ -346,50 +342,59 @@ typedef struct { scc_ast_type_t *user_type; // 如果是用户定义类型,直接存储解析结果 } type_spec_info_t; -static cbool check_type_combinations(type_spec_info_t *info) { +static cbool check_type_combinations(scc_parser_t *parser, + type_spec_info_t *info) { // 基本类型不能同时出现多个(void, char, int, float, double, bool 互斥) int basic_count = info->is_void + info->is_char + info->is_short + info->is_int + info->is_float + info->is_double + info->is_bool; if (basic_count > 1) { - LOG_ERROR("Multiple basic type specifiers"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Multiple basic type specifiers"); return false; } // long 不能与 void/char/float/bool 组合(但可以和 double 组合为 long // double) if (info->is_long && info->is_float) { - LOG_ERROR("'long' and 'float' cannot be combined"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'long' and 'float' cannot be combined"); return false; } if (info->is_long && info->is_char) { - LOG_ERROR("'long' and 'char' cannot be combined"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'long' and 'char' cannot be combined"); return false; } if (info->is_long && info->is_bool) { - LOG_ERROR("'long' and 'bool' cannot be combined"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'long' and 'bool' cannot be combined"); return false; } // long 与 double 可以组合为 long double if (info->is_long_long && info->is_double) { - LOG_ERROR("'long long' and 'double' cannot be combined"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'long long' and 'double' cannot be combined"); return false; } // short 只能与 int 组合(默认 int),不能与 double/float 等 if (info->is_short && (info->is_double || info->is_float || info->is_bool || info->is_void)) { - LOG_ERROR("'short' cannot be combined with this type"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'short' cannot be combined with this type"); return false; } // _Complex 只能与 float/double/long double 组合(或单独出现?C99 中 // _Complex 本身不是类型,必须跟浮点类型) if (info->is_complex && !info->is_float && !info->is_double) { - LOG_ERROR("'complex' must be combined with a floating type"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "'complex' must be combined with a floating type"); return false; } // 如果用户定义了类型(struct/typedef),不能与任何其他类型说明符混合 if (info->user_type != null && basic_count > 0) { - LOG_ERROR( + SCC_ERROR( + scc_parser_got_current_pos(parser), "Cannot combine user-defined type with basic type specifiers"); return false; } @@ -511,7 +516,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, while (1) { tok_ptr = scc_parser_peek(parser); if (tok_ptr == null) { - LOG_ERROR("Unexpected EOF in enum specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Unexpected EOF in enum specifier"); break; } @@ -532,7 +538,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, scc_parser_next_consume(parser, null); break; } else { - LOG_ERROR("Unexpected token in enum specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Unexpected token in enum specifier"); scc_parser_next_consume(parser, null); break; } @@ -545,6 +552,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, } else { scc_ast_decl_union_init(decl, name, &member); } + scc_parse_decl_sema(parser, decl); } scc_ast_type_t *type = ast_type_alloc(); @@ -568,7 +576,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { enumeration-constant = constant-expression */ if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) { - LOG_ERROR("Expected 'enum'"); + SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'"); return null; } const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); @@ -589,11 +597,12 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { while (1) { tok_ptr = scc_parser_peek(parser); if (tok_ptr == null) { - LOG_ERROR("Unexpected EOF in enum specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Unexpected EOF in enum specifier"); break; } - scc_ast_expr_t *expr = scc_parse_expression(parser); + scc_ast_expr_t *expr = scc_parse_assignment_expression(parser); if (expr != null) { scc_vec_push(member, expr); continue; @@ -606,7 +615,8 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { scc_parser_next_consume(parser, null); break; } else { - LOG_ERROR("Unexpected token in enum specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Unexpected token in enum specifier"); scc_parser_next_consume(parser, null); break; } @@ -614,6 +624,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); scc_ast_decl_enum_init(decl, name, &member); + scc_parse_decl_sema(parser, decl); } scc_ast_type_t *type = ast_type_alloc(); @@ -625,8 +636,36 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { type_spec_info_t info = {0}; if (!scc_parse_is_type_specifier_start(parser)) return null; + const scc_lexer_tok_t *tok_ptr = null; + tok_ptr = scc_parser_peek(parser); + + switch (tok_ptr->type) { + case SCC_TOK_STRUCT: + case SCC_TOK_UNION: + info.user_type = parse_record_type( + parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT + : SCC_AST_TYPE_UNION); + goto done; + case SCC_TOK_ENUM: + info.user_type = parse_enum_type(parser); + goto done; + case SCC_TOK_IDENT: + info.user_type = + scc_parse_got_type(parser, scc_cstring_as_cstr(&tok_ptr->lexeme)); + if (info.user_type == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected type specifier %s", + scc_cstring_as_cstr(&tok_ptr->lexeme)); + } + scc_parser_next_consume(parser, null); + Assert(info.user_type != null); + goto done; + default: + break; + } + while (1) { - const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + tok_ptr = scc_parser_peek(parser); if (tok_ptr == null) { break; } @@ -658,7 +697,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { case SCC_TOK_LONG: // long 可以出现两次 if (info.is_long_long) { - LOG_ERROR("Three 'long's in type specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Three 'long's in type specifier"); return null; } if (info.is_long) { @@ -689,7 +729,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { break; case SCC_TOK_SIGNED: if (info.is_unsigned || info.is_signed) { - LOG_ERROR("Both 'signed' and 'unsigned' in type specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Both 'signed' and 'unsigned' in type specifier"); return null; } info.is_signed = true; @@ -697,7 +738,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { break; case SCC_TOK_UNSIGNED: if (info.is_unsigned || info.is_signed) { - LOG_ERROR("Both 'signed' and 'unsigned' in type specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), + "Both 'signed' and 'unsigned' in type specifier"); return null; } info.is_unsigned = true; @@ -709,41 +751,28 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { info.is_complex = true; scc_parser_next_consume(parser, null); break; - case SCC_TOK_STRUCT: - case SCC_TOK_UNION: - info.user_type = parse_record_type( - parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT - : SCC_AST_TYPE_UNION); - goto done; - case SCC_TOK_ENUM: - info.user_type = parse_enum_type(parser); - goto done; - case SCC_TOK_IDENT: - // // 处理 typedef 名称:查符号表获取类型节点 - // info.user_type = parse_typedef_name(parser); - // if (!info.user_type) - // return null; - goto done; default: goto done; } } done: - if (!check_type_combinations(&info)) { + if (!check_type_combinations(parser, &info)) { return null; } return build_type_from_info(&info); duplicate_error: - LOG_ERROR("Duplicate type specifier"); + SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); return null; } -static scc_ast_node_t *parse_declarator(scc_parser_t *parser, +static scc_ast_type_t *parse_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr); -static scc_ast_node_t * + scc_ast_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident); +static scc_ast_type_t * parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr); + scc_ast_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident); static scc_ast_type_t * parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, scc_ast_type_t **delay_pointee_ptr); @@ -793,18 +822,15 @@ static void parse_parameter_type_list(scc_parser_t *parser, scc_ast_decl_t *param = null; while (1) { // FIXME - scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser); - scc_ast_type_t *type = parse_type_specifier(parser); - if (type == null) { - break; + scc_ast_node_t *node = _scc_parse_type(parser); + if (node == null) { + return; } - type->quals = spec; - - scc_ast_node_t *node = parse_declarator(parser, type, null); if (SCC_AST_IS_A(scc_ast_decl_t, node)) { param = SCC_AST_CAST_TO(scc_ast_decl_t, node); // TODO Check validation + Assert(param->base.type = SCC_AST_DECL_VAR); param->base.type = SCC_AST_DECL_PARAM; } else if (SCC_AST_IS_A(scc_ast_type_t, node)) { param = scc_malloc(sizeof(scc_ast_decl_t)); @@ -828,23 +854,37 @@ static void parse_parameter_type_list(scc_parser_t *parser, } } +static inline cbool parse_function_parameters_start(scc_parser_t *parser) { + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + return false; + } + if (scc_parse_is_decl_specifier_start(parser)) { + return true; + } + if (tok_ptr->type == SCC_TOK_R_PAREN) { + return true; + } + return false; +} + static void parse_function_parameters(scc_parser_t *parser, scc_ast_decl_vec_t *params) { // FIXME ? // if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { - // LOG_ERROR("Expect '('"); + // SCC_ERROR(scc_parser_got_current_pos(parser),"Expect '('"); // } scc_vec_init(*params); parse_parameter_type_list(parser, params); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("expect ')'"); + SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'"); } } static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) { const scc_lexer_tok_t *tok_ptr = null; if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) { - LOG_ERROR("Expect '['"); + SCC_ERROR(scc_parser_got_current_pos(parser), "Expect '['"); parser->errcode = 1; return null; } @@ -874,16 +914,17 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) { } } if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) { - LOG_ERROR("expect ']'"); + SCC_ERROR(scc_parser_got_current_pos(parser), "expect ']'"); parser->errcode = 1; return null; } return size; } -static scc_ast_node_t *parse_declarator(scc_parser_t *parser, +static scc_ast_type_t *parse_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr) { + scc_ast_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident) { /* (6.7.5) declarator: pointer(opt) direct-declarator @@ -901,72 +942,66 @@ static scc_ast_node_t *parse_declarator(scc_parser_t *parser, direct-declarator ( identifier-list(opt) ) */ scc_ast_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); - return parse_direct_declarator(parser, ret, delay_pointee_ptr); + return parse_direct_declarator(parser, ret, delay_pointee_ptr, tok_ident); } -static scc_ast_node_t * +static scc_ast_type_t * parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr) { + scc_ast_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident) { const scc_lexer_tok_t *tok_ptr = null; scc_ast_type_t *ret = null; // direct-abstract-declarator tok_ptr = scc_parser_peek(parser); if (tok_ptr == null) { - return (scc_ast_node_t *)base; + return base; } if (tok_ptr->type == SCC_TOK_IDENT) { - scc_lexer_tok_t tok = {0}; - scc_parser_next_consume(parser, &tok); - - scc_ast_node_t *type = - parse_direct_declarator(parser, base, delay_pointee_ptr); - Assert(SCC_AST_IS_A(scc_ast_type_t, type)); - scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t)); - Assert(decl != null); - - if (type->type == SCC_AST_TYPE_FUNCTION) { - scc_ast_decl_func_init(decl, SCC_AST_CAST_TO(scc_ast_type_t, type), - scc_cstring_as_cstr(&tok.lexeme), null); - } else { - scc_ast_decl_val_init(decl, SCC_AST_CAST_TO(scc_ast_type_t, type), - scc_cstring_as_cstr(&tok.lexeme), null); + Assert(tok_ident != null); + if (tok_ident->type != SCC_TOK_UNKNOWN) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Got double identifier in declarator"); + return base; } - return (scc_ast_node_t *)decl; + scc_parser_next_consume(parser, tok_ident); + + return parse_direct_declarator(parser, base, delay_pointee_ptr, + tok_ident); } else if (tok_ptr->type == SCC_TOK_L_PAREN) { // () SCC_TOK_L_PAREN scc_parser_next_consume(parser, null); scc_ast_type_t *delay_pointee = null; - ret = parse_abstract_declarator(parser, null, &delay_pointee); - if (ret == null) { + if (parse_function_parameters_start(parser)) { scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); ret = ast_type_alloc(); scc_ast_type_function_init(ret, base, ¶ms); - return (scc_ast_node_t *)parse_direct_declarator(parser, ret, - delay_pointee_ptr); + return parse_direct_declarator(parser, ret, delay_pointee_ptr, + tok_ident); } else { + ret = parse_declarator(parser, null, &delay_pointee, tok_ident); + Assert(ret != null); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("expect ')'"); + SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'"); } - base = (scc_ast_type_t *)parse_direct_declarator(parser, base, - delay_pointee_ptr); + base = parse_direct_declarator(parser, base, delay_pointee_ptr, + tok_ident); Assert(SCC_AST_IS_A(scc_ast_type_t, base)); Assert(delay_pointee != null); delay_pointee->pointer.pointee = base; + return ret; } - return (scc_ast_node_t *)ret; } else if (tok_ptr->type == SCC_TOK_L_BRACKET) { // [] SCC_TOK_L_BRACKET scc_ast_expr_t *size = parse_array_size_type(parser); scc_ast_type_t *ret = ast_type_alloc(); - base = (scc_ast_type_t *)parse_direct_declarator(parser, base, - delay_pointee_ptr); - Assert(SCC_AST_IS_A(scc_ast_type_t, base)); + base = + parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident); scc_ast_type_array_init(ret, base, size); - return (scc_ast_node_t *)ret; + return ret; } else { - return (scc_ast_node_t *)base; + return base; } } @@ -1008,8 +1043,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, // () SCC_TOK_L_PAREN scc_parser_next_consume(parser, null); scc_ast_type_t *delay_pointee = null; - ret = parse_abstract_declarator(parser, null, &delay_pointee); - if (ret == null) { + if (parse_function_parameters_start(parser)) { scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); ret = ast_type_alloc(); @@ -1017,8 +1051,10 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, return parse_direct_abstract_declarator(parser, ret, delay_pointee_ptr); } else { + ret = parse_abstract_declarator(parser, null, &delay_pointee); + Assert(ret != null); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - LOG_ERROR("expect ')'"); + SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'"); } base = parse_direct_abstract_declarator(parser, base, delay_pointee_ptr); @@ -1055,12 +1091,33 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) { if (ret != null) { ret->quals = spec; } - scc_ast_node_t *node = parse_declarator(parser, ret, null); - if (is_typedef_decl) { - Assert(node->type == SCC_AST_DECL_VAR); - node->type = SCC_AST_DECL_TYPEDEF; + + scc_lexer_tok_t tok_ident = {0}; + scc_ast_type_t *type = parse_declarator(parser, ret, null, &tok_ident); + + scc_ast_decl_t *decl = null; + if (tok_ident.type == SCC_TOK_IDENT) { + decl = scc_malloc(sizeof(scc_ast_decl_t)); + Assert(decl != null); } - return node; + const char *name = decl ? scc_cstring_as_cstr(&tok_ident.lexeme) : null; + if (is_typedef_decl) { + if (decl == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "typedef don't have a ident"); + parser->errcode = 1; + } else { + scc_ast_decl_typedef_init(decl, name, type); + } + } else if (decl) { + if (type->base.type == SCC_AST_TYPE_FUNCTION) { + scc_ast_decl_func_init(decl, type, name, null); + } else { + scc_ast_decl_val_init(decl, type, name, null); + } + } + + return decl != null ? &decl->base : &type->base; } scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) { diff --git a/libs/parser/src/scc_parser.c b/libs/parser/src/scc_parser.c index 35d46a7..fa2be33 100644 --- a/libs/parser/src/scc_parser.c +++ b/libs/parser/src/scc_parser.c @@ -1,5 +1,6 @@ #include #include + static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type, void *node) { (void)context; @@ -70,9 +71,10 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) { scc_vec_push(unit->declarations, decl); } else { break; - // MAYBE return or next } 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); @@ -83,6 +85,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) { if (parser->errcode) { // TODO: 清理 + SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d", + parser->errcode); scc_free(unit); return null; } diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index f1610aa..40ef9a6 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -1,6 +1,55 @@ #include #include +static void type_callback(void *context, scc_ast_node_type_t node_type, + void *node) { + scc_sema_symtab_t *sema_symtab = context; + (void)context; + (void)node_type; + (void)node; + return; +} + +static void decl_callback(void *context, scc_ast_node_type_t node_type, + void *node) { + if (node_type == SCC_AST_UNKNOWN || node == null) { + return; + } + scc_sema_symtab_t *sema_symtab = context; + scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node); + + scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); + Assert(type != null); + if (decl->name == null) { + return; + } + if (decl->base.type == SCC_AST_DECL_STRUCT) { + scc_ast_type_struct_init(type, decl->name, decl); + scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); + } else if (decl->base.type == SCC_AST_DECL_UNION) { + scc_ast_type_union_init(type, decl->name, decl); + scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); + } else if (decl->base.type == SCC_AST_DECL_ENUM) { + scc_ast_type_enum_init(type, decl->name, decl); + scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); + } else if (decl->base.type == SCC_AST_DECL_TYPEDEF) { + scc_ast_type_typedef_init(type, decl->name, decl); + scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); + } + return; +} + +static scc_ast_type_t *got_type_callback(void *context, const char *name) { + scc_sema_symtab_t *sema_symtab = context; + scc_ast_node_t *node = scc_sema_symtab_lookup_symbol(sema_symtab, name); + if (SCC_AST_IS_A(scc_ast_type_t, node)) { + scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); + *type = *(scc_ast_type_t *)node; + return type; + } + return null; +} + void scc_sema_init(scc_sema_callbacks_t *callbacks) { scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t)); if (sema_symtab == null) { @@ -8,11 +57,19 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) { return; } callbacks->context = sema_symtab; - callbacks->on_decl = null; + callbacks->on_decl = decl_callback; callbacks->on_expr = null; callbacks->on_stmt = null; - callbacks->on_type = null; - callbacks->got_type = null; + callbacks->on_type = type_callback; + callbacks->got_type = got_type_callback; + + scc_sema_symtab_init(sema_symtab); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list", + &scc_ast_builtin_type_va_list.base); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_size_t", + &scc_ast_builtin_type_long_long.base); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_ptrdiff_t", + &scc_ast_builtin_type_long_long.base); } void scc_sema_drop(scc_sema_callbacks_t *callbacks) {} diff --git a/libs/parser/src/sema_symtab.c b/libs/parser/src/sema_symtab.c index 6e3d599..a81e7ea 100644 --- a/libs/parser/src/sema_symtab.c +++ b/libs/parser/src/sema_symtab.c @@ -4,8 +4,8 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) { symtab->root_scope.parent = null; scc_hashtable_init(&symtab->root_scope.symbols, - (scc_hashtable_hash_func_t)scc_strcmp, - (scc_hashtable_equal_func_t)scc_strhash32); + (scc_hashtable_hash_func_t)scc_strhash32, + (scc_hashtable_equal_func_t)scc_strcmp); symtab->current_scope = &symtab->root_scope; } diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index b38056e..10c2471 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -7,7 +7,8 @@ typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); static scc_ast_node_t *process_input(const char *input, - scc_parse_node_func parse_func) { + scc_parse_node_func parse_func, + cbool need_sema) { int res = 0; scc_sstream_t mem_stream; res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, @@ -20,7 +21,13 @@ static scc_ast_node_t *process_input(const char *input, scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); scc_parser_t parser; - scc_parser_init(&parser, tok_ring, null); + if (need_sema) { + scc_sema_callbacks_t sema_callbacks; + scc_sema_init(&sema_callbacks); + scc_parser_init(&parser, tok_ring, &sema_callbacks); + } else { + scc_parser_init(&parser, tok_ring, null); + } scc_ast_node_t *ret = parse_func(&parser); @@ -55,8 +62,8 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) { } static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, - scc_parse_node_func parse_func) { - scc_ast_node_t *output_node_ptr = process_input(str, parse_func); + scc_parse_node_func parse_func, cbool need_sema) { + scc_ast_node_t *output_node_ptr = process_input(str, parse_func, need_sema); scc_tree_dump_ctx_t ctx; expect_buffer[0] = '\n', expect_buffer[1] = '\0'; scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); @@ -68,9 +75,19 @@ static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, scc_tree_dump_ctx_drop(&ctx); } +#define SCC_CHECK_AST_WITH_SEMA(expect_node_ptr, str, parse_func) \ + do { \ + _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ + true); \ + TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ + TEST_MSG("Expected: %s", expect_buffer); \ + TEST_MSG("Produced: %s", output_buffer); \ + } while (0); + #define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ do { \ - _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func); \ + _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ + false); \ TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ TEST_MSG("Expected: %s", expect_buffer); \ TEST_MSG("Produced: %s", output_buffer); \ @@ -370,8 +387,38 @@ static void test_parser_unit(void) { scc_ast_decl_t typedef_decl; scc_ast_decl_typedef_init(&typedef_decl, "int32_t", &scc_ast_builtin_type_int); - SCC_CHECK_AST(&typedef_decl.base, "typedef int int32_t;", - scc_parse_declaration); + scc_ast_type_t typedef_type; + scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl); + + scc_ast_decl_t i32a_decl; + scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null); + + scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base}; + scc_ast_stmt_t stmt; + scc_ast_block_item_vec_t items; + scc_vec_unsafe_from_array(items, array); + scc_ast_stmt_compound_init(&stmt, &items); + SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef int int32_t;int32_t a;}", + scc_parse_statement); + + scc_ast_type_t void_ptr; + scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); + scc_ast_decl_t void_ptr_decl; + scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr); + scc_ast_type_t void_ptr_type; + scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl); + + scc_ast_decl_t void_ptr_a_decl; + scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null); + + scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base}; + scc_vec_unsafe_from_array(items, array2); + scc_ast_stmt_compound_init(&stmt, &items); + SCC_CHECK_AST_WITH_SEMA(&stmt.base, + "{typedef void* void_ptr; void_ptr a;}", + scc_parse_statement); + SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, "typedef void *void_ptr;", + scc_parse_declaration); } { @@ -387,6 +434,145 @@ static void test_parser_unit(void) { scc_ast_decl_struct_init(&struct_def, null, &fields); SCC_CHECK_AST(&struct_def.base, "struct { int x; };", scc_parse_declaration); + + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, null, &struct_def); + scc_ast_type_t typedef_type; + scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def); + scc_ast_decl_t typedef_decl; + scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type); + SCC_CHECK_AST_WITH_SEMA(&typedef_decl.base, + "typedef struct { int x; } struct_t;", + scc_parse_declaration); + + scc_ast_decl_t typedef_impl_decl; + scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null); + scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base}; + scc_ast_stmt_t stmt; + scc_ast_block_item_vec_t items; + scc_vec_unsafe_from_array(items, array); + scc_ast_stmt_compound_init(&stmt, &items); + SCC_CHECK_AST_WITH_SEMA( + &stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}", + scc_parse_statement); + } + + { + scc_ast_decl_t type_decl; + scc_ast_decl_typedef_init(&type_decl, "size_t", + &scc_ast_builtin_type_long_long); + scc_ast_type_t type_type; + scc_ast_type_typedef_init(&type_type, "size_t", &type_decl); + + scc_ast_decl_t param1; + scc_ast_decl_param_init(¶m1, &type_type, "a"); + scc_ast_decl_t param2; + scc_ast_decl_param_init(¶m2, &scc_ast_builtin_type_int, "b"); + scc_ast_decl_t param3; + scc_ast_decl_param_init(¶m3, &scc_ast_builtin_type_va_list, null); + scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; + scc_ast_decl_vec_t func_params; + scc_vec_unsafe_from_array(func_params, params_array); + scc_ast_type_t func_type; + + scc_ast_type_t return_type; + + scc_ast_type_pointer_init(&return_type, &scc_ast_builtin_type_void); + scc_ast_type_function_init(&func_type, &return_type, &func_params); + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "func", null); + + scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl}; + scc_ast_translation_unit_t tu; + scc_ast_decl_vec_t decls; + scc_vec_unsafe_from_array(decls, decls_array); + scc_ast_translation_unit_init(&tu, &decls); + SCC_CHECK_AST_WITH_SEMA(&tu.base, + "typedef long long size_t;" + "void *func(size_t a, int b, ...);", + scc_parse_translation_unit); + + scc_ast_type_t type_func_ptr_type; + scc_ast_type_pointer_init(&type_func_ptr_type, &func_type); + scc_ast_decl_t type_func_ptr_decl; + scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t", + &type_func_ptr_type); + scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl}; + scc_vec_unsafe_from_array(decls, decls_array2); + scc_ast_translation_unit_init(&tu, &decls); + SCC_CHECK_AST_WITH_SEMA( + &tu.base, + "typedef long long size_t;" + "typedef void *(*func_t)(size_t a, int b, ...);", + scc_parse_translation_unit); + } + + { + // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) + // 步骤: + // 1) 数组类型:int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false); + scc_ast_type_t array_of_5_int; + scc_ast_type_array_init(&array_of_5_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_5); + + // 2) 函数类型:返回指向数组的指针,无参数 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_array(func_params, array); + scc_ast_type_function_init(&func_type, &ptr_to_array, + &func_params); // 无参数 + + // 3) 指向该函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type); + + scc_ast_decl_t ptr_to_func_decl; + scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null); + SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];", + scc_parse_declaration); + + scc_ast_decl_t typedef_func_decl; + scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func); + scc_ast_type_t typedef_func_type; + scc_ast_type_typedef_init(&typedef_func_type, "func_t", + &typedef_func_decl); + scc_ast_decl_t func_hard_decl; + scc_ast_type_t func_hard_type; + + scc_ast_decl_t param1; + scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar"); + scc_ast_decl_t param2; + scc_ast_decl_param_init(¶m2, &typedef_func_type, "a"); + scc_ast_decl_t param3; + scc_ast_decl_param_init(¶m1, &scc_ast_builtin_type_va_list, null); + scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; + scc_ast_decl_vec_t func_hard_params; + scc_vec_unsafe_from_array(func_hard_params, func_hard_array); + scc_ast_type_function_init(&func_hard_type, &ptr_to_array, + &func_hard_params); + scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null); + + scc_ast_decl_vec_t decls; + scc_ast_decl_t *decls_array[] = { + &typedef_func_decl, + &func_hard_decl, + }; + scc_vec_unsafe_from_array(decls, decls_array); + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &decls); + // SCC_CHECK_AST_WITH_SEMA( + // &tu.base, + // "typedef int (*(*func_t)(void))[5];" + // "int (*(*(bar)(int(*(*foo)(void))[5], func_t a, + // ...))(void))[5];", scc_parse_translation_unit); } } @@ -513,18 +699,12 @@ static void test_parser_expression(void) { // 4. 类型转换(示例: (int)x ) { - // scc_ast_type_t - // int_type; // 使用内置类型全局变量即可,但类型转换需要一个类型节点 - // // - // 我们可以直接使用全局内置类型的地址,但类型转换节点需要一个类型节点,直接引用全局即可 - // // TODO - // scc_ast_expr_t x; - // scc_ast_expr_identifier_init(&x, "x"); - // scc_ast_expr_t cast; - // scc_ast_expr_cast_init(&cast, - // (scc_ast_type_t *)&scc_ast_builtin_type_int, - // &x); - // SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); + scc_ast_expr_t x; + scc_ast_expr_identifier_init(&x, "x"); + scc_ast_expr_t cast; + scc_ast_expr_cast_init(&cast, + (scc_ast_type_t *)&scc_ast_builtin_type_int, &x); + SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); } // 5. 二元运算符优先级 @@ -1168,10 +1348,8 @@ static void test_parser_type(void) { scc_ast_expr_identifier_init(&green, "GREEN"); scc_ast_expr_identifier_init(&blue, "BLUE"); scc_ast_expr_vec_t enumerators; - scc_vec_init(enumerators); - scc_vec_push(enumerators, &red); - scc_vec_push(enumerators, &green); - scc_vec_push(enumerators, &blue); + scc_ast_expr_t *array[] = {&red, &green, &blue}; + scc_vec_unsafe_from_array(enumerators, array); scc_ast_decl_t enum_def; scc_ast_decl_enum_init(&enum_def, null, &enumerators); @@ -1179,9 +1357,11 @@ static void test_parser_type(void) { scc_ast_type_enum_init(&enum_type, null, &enum_def); SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", _scc_parse_type); + + scc_vec_unsafe_from_array(enumerators, array); scc_ast_decl_enum_init(&enum_def, "E", &enumerators); scc_ast_type_enum_init(&enum_type, "E", &enum_def); - SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE }", + SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }", _scc_parse_type); } diff --git a/libs/pproc/src/pproc_directive.c b/libs/pproc/src/pproc_directive.c index 95122c6..068f14b 100644 --- a/libs/pproc/src/pproc_directive.c +++ b/libs/pproc/src/pproc_directive.c @@ -90,6 +90,10 @@ static inline void fill_replacements(scc_pproc_t *pp, scc_ring_next_consume(*pp->cur_ring, tok, ok); if (!ok) break; + if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_COMMENT) { + scc_lexer_tok_drop(&tok); + continue; + } if (tok.type == SCC_TOK_EOF || tok.type == SCC_TOK_ENDLINE) { scc_lexer_tok_drop(&tok); break; diff --git a/libs/pproc/src/pproc_macro.c b/libs/pproc/src/pproc_macro.c index f45ff79..9cc085b 100644 --- a/libs/pproc/src/pproc_macro.c +++ b/libs/pproc/src/pproc_macro.c @@ -96,10 +96,10 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros, scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp, scc_pproc_macro_t *macro) { - Assert(pp != null && macro != null); + Assert(pp != null && macro != null && scc_cstring_len(¯o->name) != 0); scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, ¯o->name, macro); if (old && old != macro) { - LOG_WARN("same macro name"); + LOG_WARN("same macro name `%s`", scc_cstring_as_cstr(¯o->name)); scc_pproc_macro_drop(old); } return macro; diff --git a/libs/pproc/tests/test_pproc_unit.c b/libs/pproc/tests/test_pproc_unit.c index 710915d..8fd8d9d 100644 --- a/libs/pproc/tests/test_pproc_unit.c +++ b/libs/pproc/tests/test_pproc_unit.c @@ -194,6 +194,11 @@ static void test_define_nested_macros(void) { CHECK_PP_OUTPUT_EXACT("#define default a\n" "default\n", "a\n"); + + TEST_CASE("test_macro_end_by_comment"); + CHECK_PP_OUTPUT_EXACT("#define MAX_SIZE 128///! COMMENT\n" + "MAX_SIZE\n", + "128\n"); } static void test_undef_macros(void) { diff --git a/runtime/scc_core/include/scc_core_type.h b/runtime/scc_core/include/scc_core_type.h index 0cb81c8..e844eee 100644 --- a/runtime/scc_core/include/scc_core_type.h +++ b/runtime/scc_core/include/scc_core_type.h @@ -34,25 +34,29 @@ static_assert(sizeof(cbool) == 1, "cbool size must 1"); #else /* clang-format off */ -typedef __scc_i8 i8; -typedef __scc_i16 i16; -typedef __scc_i32 i32; -typedef __scc_i64 i64; -typedef __scc_u8 u8; -typedef __scc_u16 u16; -typedef __scc_u32 u32; -typedef __scc_u64 u64; -typedef __scc_isize isize; -typedef __scc_usize usize; -typedef __scc_isize pdiff; +#include +#include +#include +#include -typedef __scc_f32 f32; -typedef __scc_f64 f64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; -typedef __scc_bool cbool; -/// void / null -#define null __scc_null +typedef intptr_t isize; +typedef uintptr_t usize; +typedef ptrdiff_t pdiff; + +typedef float f32; +typedef double f64; + +typedef bool cbool; /* clang-format on */ #endif diff --git a/runtime/scc_core/src/cfg.std_impl.c b/runtime/scc_core/src/cfg.std_impl.c index adc36ac..e8f2f4e 100644 --- a/runtime/scc_core/src/cfg.std_impl.c +++ b/runtime/scc_core/src/cfg.std_impl.c @@ -10,6 +10,10 @@ #include #include +#ifdef __SCC__ // FIXME it will be remove +typedef void *FILE; +#endif + void *scc_pal_malloc(size_t size) { return malloc(size); } void *scc_pal_calloc(size_t count, size_t size) { return calloc(count, size); }