feat(parser): 添加声明列表支持并重构解析逻辑

- 添加 SCC_AST_DECL_LIST 节点类型用于表示声明列表
- 实现 scc_ast_decl_list_init 函数来初始化声明列表节点
- 重构 scc_parse_declaration 函数以支持逗号分隔的多个变量声明
- 分离类型说明符解析到独立的 scc_parse_declaration_specifiers 函数
- 支持 typedef 和多变量声明如 'int a, b;' 和 'int a = 1, b = 2;'
- 在 ast_dump 中添加对声明列表节点的打印支持

refactor(ast): 统一使用 scc_vec_foreach 宏替换手动循环

- 将 ast_dump.c 中的多个手动索引循环改为使用 scc_vec_foreach
- 提高代码可读性和安全性
- 避免索引越界错误

fix(parser): 修复语义分析中结构体符号表冲突

- 为结构体、联合体和枚举符号名添加前缀避免命名冲突
- 使用 '$S_'、'$U_'、'$E_' 前缀分别标识结构体、联合体和枚举

refactor(log): 统一终止处理方式

- 将 log_exit 替换为 log_abort 以更准确反映行为
- 更新相关依赖模块的实现

style(parser): 移除未使用的参数和清理代码

- 在 argparse.c 中添加 (void) 参数注释处理未使用的参数
- 清理 parse_expr.c 中未使用的函数声明
- 优化 parse_type.c 中的错误处理流程
This commit is contained in:
zzy
2026-03-14 14:04:24 +08:00
parent 8fcfeda14e
commit eb969cdbf7
26 changed files with 344 additions and 165 deletions

View File

@@ -116,6 +116,7 @@ static void init_context(scc_argparse_context_t *ctx, scc_argparse_t *parser,
static int handle_parse_error(scc_argparse_t *parser, static int handle_parse_error(scc_argparse_t *parser,
scc_argparse_context_t *ctx) { scc_argparse_context_t *ctx) {
(void)parser; // TODO
scc_argparse_err_t error = SCC_ARGPARSE_ERR_NONE; scc_argparse_err_t error = SCC_ARGPARSE_ERR_NONE;
switch (ctx->result.error) { switch (ctx->result.error) {
case SCC_OPT_ERROR_NOT_FOUND_SHORT_ARG: case SCC_OPT_ERROR_NOT_FOUND_SHORT_ARG:
@@ -138,6 +139,7 @@ static int handle_parse_error(scc_argparse_t *parser,
static int validate_and_cleanup(scc_argparse_context_t *ctx, static int validate_and_cleanup(scc_argparse_context_t *ctx,
scc_argparse_t *parser, int errcode) { scc_argparse_t *parser, int errcode) {
(void)parser; // TODO
if (errcode == SCC_ARGPARSE_ERR_NONE) { if (errcode == SCC_ARGPARSE_ERR_NONE) {
// 检查必需参数是否都已提供 // 检查必需参数是否都已提供
scc_vec_foreach(ctx->current_cmd->args, i) { scc_vec_foreach(ctx->current_cmd->args, i) {
@@ -213,6 +215,7 @@ static int handle_option(scc_argparse_context_t *ctx, scc_argparse_t *parser) {
static int handle_positional_arg(scc_argparse_context_t *ctx, static int handle_positional_arg(scc_argparse_context_t *ctx,
scc_argparse_t *parser) { scc_argparse_t *parser) {
(void)parser; // TODO
scc_argparse_cmd_t *subcmd = scc_argparse_cmd_t *subcmd =
is_subcommand(ctx->current_cmd, ctx->result.value); is_subcommand(ctx->current_cmd, ctx->result.value);
if (subcmd != NULL) { if (subcmd != NULL) {

View File

@@ -11,6 +11,7 @@ typedef enum {
SCC_AST_UNKNOWN, SCC_AST_UNKNOWN,
// 声明 // 声明
scc_ast_decl_t_BEGIN, // 声明开始 scc_ast_decl_t_BEGIN, // 声明开始
SCC_AST_DECL_LIST, // 声明列表
SCC_AST_DECL_VAR, // 变量声明 SCC_AST_DECL_VAR, // 变量声明
SCC_AST_DECL_FUNC, // 函数声明 SCC_AST_DECL_FUNC, // 函数声明
SCC_AST_DECL_PARAM, // 参数声明 SCC_AST_DECL_PARAM, // 参数声明
@@ -417,6 +418,9 @@ struct scc_ast_decl {
scc_ast_node_t base; scc_ast_node_t base;
const char *name; const char *name;
union { union {
struct {
scc_ast_decl_vec_t vars;
} list;
// 变量声明 // 变量声明
struct { struct {
scc_ast_type_t *type; scc_ast_type_t *type;

View File

@@ -20,6 +20,16 @@ scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
} }
} }
static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
scc_ast_decl_vec_t *list_move) {
Assert(decl != null && list_move != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_LIST;
decl->name = null;
decl->list.vars = *list_move;
scc_vec_init(*list_move);
}
// name and var_init can be null // name and var_init can be null
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, scc_ast_type_t *type,

View File

@@ -17,6 +17,7 @@
static const char *node_type_names[] = { static const char *node_type_names[] = {
[SCC_AST_UNKNOWN] = "Unknown", [SCC_AST_UNKNOWN] = "Unknown",
[scc_ast_decl_t_BEGIN] = "ERROR", [scc_ast_decl_t_BEGIN] = "ERROR",
[SCC_AST_DECL_LIST] = "DeclList",
[SCC_AST_DECL_VAR] = "VarDecl", [SCC_AST_DECL_VAR] = "VarDecl",
[SCC_AST_DECL_FUNC] = "FuncDecl", [SCC_AST_DECL_FUNC] = "FuncDecl",
[SCC_AST_DECL_PARAM] = "ParamDecl", [SCC_AST_DECL_PARAM] = "ParamDecl",
@@ -224,7 +225,7 @@ static inline void dump_child_node(scc_ast_node_t *child,
scc_vec_push(ctx->stack, is_last); scc_vec_push(ctx->stack, is_last);
scc_ast_dump_node(ctx, child); scc_ast_dump_node(ctx, child);
scc_vec_pop(ctx->stack); (void)scc_vec_pop(ctx->stack);
} }
// 用于构建复合类型名称的宏 // 用于构建复合类型名称的宏
@@ -343,7 +344,7 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s\n", "ReturnType"); SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s\n", "ReturnType");
dump_child_node((scc_ast_node_t *)type->function.return_type, ctx, dump_child_node((scc_ast_node_t *)type->function.return_type, ctx,
true); true);
scc_vec_pop(ctx->stack); (void)scc_vec_pop(ctx->stack);
scc_vec_push(ctx->stack, true); scc_vec_push(ctx->stack, true);
if (scc_vec_size(type->function.param_types) != 0) { if (scc_vec_size(type->function.param_types) != 0) {
@@ -360,7 +361,7 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
PRINT_QUOTED_VALUE(ctx, "()"); PRINT_QUOTED_VALUE(ctx, "()");
scc_tree_dump_printf(ctx, "\n"); scc_tree_dump_printf(ctx, "\n");
} }
scc_vec_pop(ctx->stack); (void)scc_vec_pop(ctx->stack);
break; break;
default: default:
break; break;
@@ -445,7 +446,7 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
ctx, ctx->node_color, "%s %s\n", ctx, ctx->node_color, "%s %s\n",
expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember", expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember",
expr->member.name); expr->member.name);
scc_vec_pop(ctx->stack); (void)scc_vec_pop(ctx->stack);
break; break;
case SCC_AST_EXPR_CAST: case SCC_AST_EXPR_CAST:
@@ -563,11 +564,10 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
break; break;
case SCC_AST_STMT_COMPOUND: case SCC_AST_STMT_COMPOUND:
end_node_dump(ctx); end_node_dump(ctx);
for (size_t i = 0; i < stmt->compound.block_items.size; i++) { scc_vec_foreach(stmt->compound.block_items, i) {
scc_ast_node_t *item = dump_child_node(
(scc_ast_node_t *)stmt->compound.block_items.data[i]; (scc_ast_node_t *)scc_vec_at(stmt->compound.block_items, i),
dump_child_node(item, ctx, ctx, i + 1 == stmt->compound.block_items.size);
i == stmt->compound.block_items.size - 1);
} }
break; break;
@@ -613,6 +613,12 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) {
// 递归转储子节点 // 递归转储子节点
switch (decl->base.type) { switch (decl->base.type) {
case SCC_AST_DECL_LIST:
scc_vec_foreach(decl->list.vars, i) {
dump_child_node((scc_ast_node_t *)scc_vec_at(decl->list.vars, i),
ctx, i + 1 != scc_vec_size(decl->list.vars));
}
break;
case SCC_AST_DECL_VAR: case SCC_AST_DECL_VAR:
if (decl->var.type) { if (decl->var.type) {
dump_child_node((scc_ast_node_t *)decl->var.type, ctx, dump_child_node((scc_ast_node_t *)decl->var.type, ctx,
@@ -641,17 +647,18 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) {
case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_STRUCT:
case SCC_AST_DECL_UNION: case SCC_AST_DECL_UNION:
for (size_t i = 0; i < decl->record.fields.size; i++) { scc_vec_foreach(decl->record.fields, i) {
dump_child_node((scc_ast_node_t *)decl->record.fields.data[i], ctx, dump_child_node(
i == decl->record.fields.size - 1); (scc_ast_node_t *)scc_vec_at(decl->record.fields, i), ctx,
i + 1 != scc_vec_size(decl->record.fields));
} }
break; break;
case SCC_AST_DECL_ENUM: case SCC_AST_DECL_ENUM:
for (size_t i = 0; i < decl->enumeration.enumerators.size; i++) { scc_vec_foreach(decl->enumeration.enumerators, i) {
dump_child_node( dump_child_node(
(scc_ast_node_t *)decl->enumeration.enumerators.data[i], ctx, (scc_ast_node_t *)scc_vec_at(decl->enumeration.enumerators, i),
i == decl->enumeration.enumerators.size - 1); ctx, i + 1 != scc_vec_size(decl->enumeration.enumerators));
} }
break; break;
@@ -675,9 +682,9 @@ static void dump_unit_impl(scc_ast_translation_unit_t *unit,
start_node_dump(&unit->base, ctx); start_node_dump(&unit->base, ctx);
end_node_dump(ctx); end_node_dump(ctx);
for (size_t i = 0; i < unit->declarations.size; i++) { scc_vec_foreach(unit->declarations, i) {
dump_child_node((scc_ast_node_t *)unit->declarations.data[i], ctx, dump_child_node((scc_ast_node_t *)scc_vec_at(unit->declarations, i),
i == unit->declarations.size - 1); ctx, i + 1 != scc_vec_size(unit->declarations));
} }
} }

View File

@@ -75,7 +75,9 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser);
* @param parser 解析器实例 * @param parser 解析器实例
* @return 类型 AST 节点 * @return 类型 AST 节点
*/ */
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser); scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
scc_ast_type_t *type);
scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser);
scc_ast_type_t *scc_parse_type_name(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, static inline void scc_parse_decl_sema(scc_parser_t *parser,

View File

@@ -258,25 +258,33 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
} }
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
scc_ast_decl_t *decl = scc_parse_declarator(parser); const scc_lexer_tok_t *tok_ptr = null;
scc_ast_decl_t *decl_list = null;
scc_ast_decl_vec_t decl_list_vec;
scc_vec_init(decl_list_vec);
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
if (type == null) {
return null;
}
scc_ast_decl_specifier_t spec = type->quals;
// FIXME drop typedef inline and ...
type->quals.is_typedef = false;
scc_ast_decl_t *decl = null;
CONTINUE:
decl = scc_parse_declarator(parser, type);
if (decl == null) { if (decl == null) {
return null; return null;
} }
tok_ptr = scc_parser_peek(parser);
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); if (tok_ptr->type == SCC_TOK_ASSIGN) {
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
scc_parser_next_consume(parser, null);
goto RETURN;
} else if (tok_ptr->type == SCC_TOK_ASSIGN) {
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
// TODO maybe memory leak // TODO maybe memory leak
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t)); scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t));
scc_ast_expr_lvalue_init(lvalue, decl->var.type); scc_ast_expr_lvalue_init(lvalue, decl->var.type);
decl->var.init = scc_parse_initializer(parser, lvalue); decl->var.init = scc_parse_initializer(parser, lvalue);
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon");
}
goto RETURN;
} else if (tok_ptr->type == SCC_TOK_L_BRACE) { } else if (tok_ptr->type == SCC_TOK_L_BRACE) {
scc_ast_stmt_t *body = scc_parse_statement(parser); scc_ast_stmt_t *body = scc_parse_statement(parser);
Assert(decl->base.type == SCC_AST_DECL_FUNC); Assert(decl->base.type == SCC_AST_DECL_FUNC);
@@ -285,13 +293,56 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION); Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION);
Assert(decl->func.body != null); Assert(decl->func.body != null);
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND); Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
goto RETURN;
}
tok_ptr = scc_parser_peek(parser);
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
scc_parser_next_consume(parser, null);
if (spec.is_typedef) {
if (decl_list) {
scc_vec_foreach(decl_list_vec, i) {
decl = scc_vec_at(decl_list_vec, i);
scc_ast_decl_typedef_init(decl, decl->name, type);
}
} else {
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
}
}
if (decl_list != null) {
scc_vec_push(decl_list_vec, decl);
scc_vec_foreach(decl_list_vec, i) {
decl = scc_vec_at(decl_list_vec, i);
scc_parse_decl_sema(parser, decl);
}
scc_ast_decl_list_init(decl_list, &decl_list_vec);
decl = decl_list;
} else {
scc_parse_decl_sema(parser, decl);
}
goto RETURN;
} else if (tok_ptr->type == SCC_TOK_COMMA) {
scc_parser_next_consume(parser, null);
if (decl_list == null) {
decl_list = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl_list != null);
scc_vec_push(decl_list_vec, decl);
} else {
Assert(scc_vec_size(decl_list_vec) != 0);
decl->var.type = scc_vec_at(decl_list_vec, 0)->var.type;
scc_vec_push(decl_list_vec, decl);
}
goto CONTINUE;
} else { } else {
SCC_ERROR(scc_parser_got_current_pos(parser), SCC_ERROR(scc_parser_got_current_pos(parser),
"Expected ';' or '=' or '{'"); "Expected ';' or '=' or '{'");
UNREACHABLE(); // FIXME memory leak
goto ERROR;
} }
RETURN: RETURN:
scc_parse_decl_sema(parser, decl);
return decl; return decl;
ERROR:
return null;
} }

View File

@@ -149,8 +149,6 @@ parse_primary_expression(scc_parser_t *parser); // 基本表达式
// 特殊结构的内部辅助函数 // 特殊结构的内部辅助函数
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser); static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser);
static scc_ast_expr_t *
parse_paren_expression(scc_parser_t *parser); // 处理括号的三种情况
/* ---------------------------- 工具函数 ---------------------------- */ /* ---------------------------- 工具函数 ---------------------------- */
// 获取 token 的优先级(用于二元运算符) // 获取 token 的优先级(用于二元运算符)
@@ -537,11 +535,10 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
case SCC_TOK_BIT_NOT: // ~x case SCC_TOK_BIT_NOT: // ~x
case SCC_TOK_NOT: // !x case SCC_TOK_NOT: // !x
{ {
scc_lexer_tok_t op_tok; if (!scc_parser_next_consume(parser, &tok))
if (!scc_parser_next_consume(parser, &op_tok))
return null; return null;
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, true); scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
scc_lexer_tok_drop(&op_tok); scc_lexer_tok_drop(&tok);
// 一元运算符右结合,递归调用 parse_unary_expression // 一元运算符右结合,递归调用 parse_unary_expression

View File

@@ -588,10 +588,13 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
break; break;
} }
decl = scc_parse_declarator(parser); scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
if (decl != null) { if (type != null) {
scc_vec_push(member, decl); decl = scc_parse_declarator(parser, type);
continue; if (decl != null) {
scc_vec_push(member, decl);
continue;
}
} }
if (tok_ptr->type == SCC_TOK_SEMICOLON) { if (tok_ptr->type == SCC_TOK_SEMICOLON) {
@@ -893,11 +896,16 @@ static void parse_parameter_type_list(scc_parser_t *parser,
declaration-specifiers abstract-declarator(opt) declaration-specifiers abstract-declarator(opt)
*/ */
scc_ast_decl_t *param = null; scc_ast_decl_t *param = null;
scc_ast_decl_t *decl = null;
while (1) { while (1) {
// FIXME // FIXME
scc_ast_decl_t *decl = scc_parse_declarator(parser); scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
if (type == null) {
break;
}
decl = scc_parse_declarator(parser, type);
if (decl == null) { if (decl == null) {
return; break;
} }
// TODO Check validation // TODO Check validation
@@ -1142,87 +1150,142 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
} }
} }
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser) { scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
if (!scc_parse_is_decl_specifier_start(parser)) { scc_ast_type_t *type) {
return null; scc_lexer_tok_t decl_name_tok = {0};
} scc_ast_type_t *decl_type =
parse_declarator(parser, type, null, &decl_name_tok);
cbool is_typedef_decl = false;
if (scc_parser_consume_if(parser, SCC_TOK_TYPEDEF)) {
is_typedef_decl = true;
}
scc_ast_type_t *ret = null;
scc_ast_decl_specifier_t spec = {0};
spec = parse_declaration_specifiers_list(parser, spec);
ret = parse_type_specifier(parser);
if (ret != null) {
ret->quals = spec;
ret->quals.is_inline = false;
}
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; scc_ast_decl_t *decl = null;
if (tok_ident.type == SCC_TOK_IDENT) { decl = scc_malloc(sizeof(scc_ast_decl_t));
decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null);
Assert(decl != null); Assert(decl_name_tok.type == SCC_TOK_IDENT ||
} decl_name_tok.type == SCC_TOK_UNKNOWN);
const char *name = decl ? scc_cstring_as_cstr(&tok_ident.lexeme) : null;
if (is_typedef_decl) { // FIXME memory leak
if (decl == null) { const char *name = decl_name_tok.type == SCC_TOK_IDENT
SCC_ERROR(scc_parser_got_current_pos(parser), ? scc_cstring_as_cstr(&decl_name_tok.lexeme)
"typedef don't have a ident"); : null;
parser->errcode = 1;
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
scc_ast_decl_func_init(decl, decl_type, name, null);
// TODO using sema to change it
if (type->quals.is_inline) {
decl_type->quals.is_inline = true;
} else { } else {
scc_ast_decl_typedef_init(decl, name, type); type->quals.is_inline = false;
}
} else if (decl) {
if (type->base.type == SCC_AST_TYPE_FUNCTION) {
scc_ast_decl_func_init(decl, type, name, null);
// TODO using sema to change it
if (spec.is_inline) {
type->quals.is_inline = true;
}
} else {
scc_ast_decl_val_init(decl, type, name, null);
} }
} else {
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null);
} }
scc_ast_node_t *type_or_decl = decl != null ? &decl->base : &type->base; if (decl_name_tok.type != SCC_TOK_IDENT) {
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) { if (decl_type->base.type == SCC_AST_TYPE_STRUCT ||
scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl); decl_type->base.type == SCC_AST_TYPE_UNION) {
if (type->base.type == SCC_AST_TYPE_STRUCT || if (decl_type->record.decl == null) {
type->base.type == SCC_AST_TYPE_UNION) {
if (type->record.decl == null) {
SCC_ERROR(scc_parser_got_current_pos(parser), SCC_ERROR(scc_parser_got_current_pos(parser),
"record don't have a decl"); "record don't have a decl");
Panic(); Panic();
} }
decl = type->record.decl; decl = decl_type->record.decl;
scc_free(type_or_decl); // FIXME scc_free(decl_type); // FIXME
} else if (type->base.type == SCC_AST_TYPE_ENUM) { } else if (decl_type->base.type == SCC_AST_TYPE_ENUM) {
if (type->enumeration.decl == null) { if (decl_type->enumeration.decl == null) {
SCC_ERROR(scc_parser_got_current_pos(parser), SCC_ERROR(scc_parser_got_current_pos(parser),
"enum don't have a decl"); "enum don't have a decl");
Panic(); Panic();
} }
decl = type->enumeration.decl; decl = type->enumeration.decl;
scc_free(type_or_decl); // FIXME scc_free(decl_type); // FIXME
} else { } else {
decl = scc_malloc(sizeof(scc_ast_decl_t)); decl = scc_malloc(sizeof(scc_ast_decl_t));
scc_ast_decl_unsafe_val_init(decl, type, null, null); scc_ast_decl_unsafe_val_init(decl, type, null, null);
} }
} 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 {
SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
return null;
} }
return decl; return decl;
} }
scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
if (!scc_parse_is_decl_specifier_start(parser)) {
return null;
}
scc_ast_decl_specifier_t spec = {0};
if (scc_parser_consume_if(parser, SCC_TOK_TYPEDEF)) {
spec.is_typedef = true;
}
spec = parse_declaration_specifiers_list(parser, spec);
scc_ast_type_t *specifier = parse_type_specifier(parser);
if (specifier == null) {
SCC_ERROR(scc_parser_got_current_pos(parser),
"declaration specifier can't have type specifier");
return null;
}
specifier->quals = spec;
return specifier;
// 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);
// }
// 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);
// // TODO using sema to change it
// if (spec.is_inline) {
// type->quals.is_inline = true;
// }
// } else {
// scc_ast_decl_val_init(decl, type, name, null);
// }
// }
// scc_ast_node_t *type_or_decl = decl != null ? &decl->base : &type->base;
// if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
// scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
// if (type->base.type == SCC_AST_TYPE_STRUCT ||
// type->base.type == SCC_AST_TYPE_UNION) {
// if (type->record.decl == null) {
// SCC_ERROR(scc_parser_got_current_pos(parser),
// "record don't have a decl");
// Panic();
// }
// decl = type->record.decl;
// scc_free(type_or_decl); // FIXME
// } else if (type->base.type == SCC_AST_TYPE_ENUM) {
// if (type->enumeration.decl == null) {
// SCC_ERROR(scc_parser_got_current_pos(parser),
// "enum don't have a decl");
// Panic();
// }
// decl = type->enumeration.decl;
// scc_free(type_or_decl); // FIXME
// } else {
// decl = scc_malloc(sizeof(scc_ast_decl_t));
// scc_ast_decl_unsafe_val_init(decl, type, null, null);
// }
// } 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 {
// SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
// return null;
// }
// return decl;
}
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) { scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
if (!(scc_parse_is_type_specifier_start(parser) || if (!(scc_parse_is_type_specifier_start(parser) ||
scc_parse_is_type_qualifier_start(parser))) { scc_parse_is_type_qualifier_start(parser))) {

View File

@@ -64,7 +64,6 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
* same as * same as
* Program := Declaration* Definition* * Program := Declaration* Definition*
*/ */
cbool matched = false;
while (1) { while (1) {
scc_ast_decl_t *decl = scc_parse_declaration(parser); scc_ast_decl_t *decl = scc_parse_declaration(parser);
if (decl != null) { if (decl != null) {

View File

@@ -25,13 +25,22 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
} }
if (decl->base.type == SCC_AST_DECL_STRUCT) { if (decl->base.type == SCC_AST_DECL_STRUCT) {
scc_ast_type_struct_init(type, decl->name, decl); scc_ast_type_struct_init(type, decl->name, decl);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); scc_cstring_t name = scc_cstring_from_cstr("$S_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base);
} else if (decl->base.type == SCC_AST_DECL_UNION) { } else if (decl->base.type == SCC_AST_DECL_UNION) {
scc_ast_type_union_init(type, decl->name, decl); scc_ast_type_union_init(type, decl->name, decl);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); scc_cstring_t name = scc_cstring_from_cstr("$U_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base);
} else if (decl->base.type == SCC_AST_DECL_ENUM) { } else if (decl->base.type == SCC_AST_DECL_ENUM) {
scc_ast_type_enum_init(type, decl->name, decl); scc_ast_type_enum_init(type, decl->name, decl);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); scc_cstring_t name = scc_cstring_from_cstr("$E_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base);
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) { } else if (decl->base.type == SCC_AST_DECL_TYPEDEF) {
scc_ast_type_typedef_init(type, decl->name, decl); scc_ast_type_typedef_init(type, decl->name, decl);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);

View File

@@ -23,8 +23,9 @@ void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) {
return; return;
} }
scope->parent = symtab->current_scope; scope->parent = symtab->current_scope;
scc_hashtable_init(&scope->symbols, (scc_hashtable_hash_func_t)scc_strcmp, scc_hashtable_init(&scope->symbols,
(scc_hashtable_equal_func_t)scc_strhash32); (scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp);
symtab->current_scope = scope; symtab->current_scope = scope;
} }

View File

@@ -689,55 +689,57 @@ static void test_parser_unit(void) {
scc_parse_declaration); scc_parse_declaration);
} }
// // 测试 int a, b; // 测试 int a, b;
// { {
// scc_ast_decl_t decl_a, decl_b; scc_ast_decl_t decl_a, decl_b;
// scc_ast_decl_val_init(&decl_a, scc_ast_decl_val_init(&decl_a,
// (scc_ast_type_t (scc_ast_type_t *)&scc_ast_builtin_type_int,
// *)&scc_ast_builtin_type_int, "a", null); "a", null);
// scc_ast_decl_val_init(&decl_b, scc_ast_decl_val_init(&decl_b,
// (scc_ast_type_t (scc_ast_type_t *)&scc_ast_builtin_type_int,
// *)&scc_ast_builtin_type_int, "b", null); "b", null);
// scc_ast_decl_vec_t decl_vec; scc_ast_decl_vec_t decl_vec;
// scc_vec_init(decl_vec); scc_vec_init(decl_vec);
// scc_vec_push(decl_vec, &decl_a); scc_vec_push(decl_vec, &decl_a);
// scc_vec_push(decl_vec, &decl_b); scc_vec_push(decl_vec, &decl_b);
// scc_ast_decl_t decl_list; scc_ast_decl_t decl_list;
// scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数
// SCC_CHECK_AST(&decl_list.base, "int a, b;", SCC_CHECK_AST(&decl_list.base, "int a, b;", scc_parse_declaration);
// scc_parse_declaration); }
// }
// // 测试 int a = 1, b = 2; // 测试 int a = 1, b = 2;
// { {
// scc_ast_expr_t lit1, lit2; scc_ast_expr_t lit1, lit2;
// scc_ast_expr_literal_int_init(&lit1, "1", false); scc_ast_expr_literal_int_init(&lit1, "1", false);
// scc_ast_expr_literal_int_init(&lit2, "2", false); scc_ast_expr_literal_int_init(&lit2, "2", false);
// scc_ast_decl_t decl_a, decl_b; scc_ast_decl_t decl_a, decl_b;
// scc_ast_decl_val_init(&decl_a, scc_ast_decl_val_init(&decl_a,
// (scc_ast_type_t (scc_ast_type_t *)&scc_ast_builtin_type_int,
// *)&scc_ast_builtin_type_int, "a", &lit1); "a", &lit1);
// scc_ast_decl_val_init(&decl_b, scc_ast_decl_val_init(&decl_b,
// (scc_ast_type_t (scc_ast_type_t *)&scc_ast_builtin_type_int,
// *)&scc_ast_builtin_type_int, "b", &lit2); "b", &lit2);
// scc_ast_decl_vec_t decl_vec; scc_ast_decl_vec_t decl_vec;
// scc_vec_init(decl_vec); scc_vec_init(decl_vec);
// scc_vec_push(decl_vec, &decl_a); scc_vec_push(decl_vec, &decl_a);
// scc_vec_push(decl_vec, &decl_b); scc_vec_push(decl_vec, &decl_b);
// scc_ast_decl_t decl_list; scc_ast_decl_t decl_list;
// scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数
// SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;", SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;",
// scc_parse_declaration); scc_parse_declaration);
// } }
"struct list_head *next, *prev;";
"typedef struct { int a; } struct_t, *struct_ptr_t;";
"__scc_builtin_va_arg(ag, int)"; "__scc_builtin_va_arg(ag, int)";
"__scc_builtin_va_arg(ag, long long)"; "__scc_builtin_va_arg(ag, long long)";
"typedef struct a;int a;struct a b;";
} }
{ {

View File

@@ -68,7 +68,7 @@ static void in_endif(scc_pproc_t *pp) {
if (scc_vec_size(pp->if_stack) == 0) { if (scc_vec_size(pp->if_stack) == 0) {
LOG_ERROR("#endif without #if"); LOG_ERROR("#endif without #if");
} else { } else {
scc_vec_pop(pp->if_stack); (void)scc_vec_pop(pp->if_stack);
} }
if (scc_vec_size(pp->if_stack) == 0) { if (scc_vec_size(pp->if_stack) == 0) {
pp->enable = true; pp->enable = true;
@@ -136,6 +136,7 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
static int parse_constant_condition(scc_pproc_t *pp, static int parse_constant_condition(scc_pproc_t *pp,
scc_lexer_tok_ring_t *tok_ring) { scc_lexer_tok_ring_t *tok_ring) {
(void)pp; // TODO
int ok; int ok;
scc_lexer_tok_t tok = {0}; scc_lexer_tok_t tok = {0};
ok = scc_lexer_next_non_blank(tok_ring, &tok); ok = scc_lexer_next_non_blank(tok_ring, &tok);

View File

@@ -44,8 +44,9 @@ static int user_log_handler(logger_t *module, log_level_t level,
log_puts(buf); log_puts(buf);
log_puts("\n"); log_puts("\n");
if (level == LOG_LEVEL_FATAL) if (level == LOG_LEVEL_FATAL) {
log_exit(1); log_abort();
}
return 0; return 0;
} }

View File

@@ -67,6 +67,7 @@ static int sstream_scan_at(scc_sstream_t *stream, scc_pos_t scan_pos,
// 环形缓冲区填充回调(通过 userdata 获取流对象) // 环形缓冲区填充回调(通过 userdata 获取流对象)
static cbool fill_func(scc_sstream_char_t *out, void *userdata) { static cbool fill_func(scc_sstream_char_t *out, void *userdata) {
Assert(out != null && userdata != null);
scc_sstream_t *stream = (scc_sstream_t *)userdata; scc_sstream_t *stream = (scc_sstream_t *)userdata;
if (stream->fill_pos.offset >= stream->len) if (stream->fill_pos.offset >= stream->len)
return false; // 已到文件尾 return false; // 已到文件尾

View File

@@ -66,7 +66,7 @@ static inline void scc_tree_dump_ctx_drop(scc_tree_dump_ctx_t *ctx) {
} }
// 打印缩进 // 打印缩进
static void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) { static inline void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->stack, i) { scc_vec_foreach(ctx->stack, i) {
cbool last_child = scc_vec_at(ctx->stack, i); cbool last_child = scc_vec_at(ctx->stack, i);
const char *data = null; const char *data = null;

View File

@@ -60,7 +60,7 @@ int log_default_handler(logger_t *module, log_level_t level, const char *file,
(void)color_code; (void)color_code;
(void)level_str; (void)level_str;
if (level & LOG_LEVEL_FATAL) { if (level & LOG_LEVEL_FATAL) {
log_exit(-LOG_LEVEL_FATAL); log_abort();
} }
return 0; return 0;
} }

View File

@@ -14,7 +14,7 @@
#include <stdlib.h> #include <stdlib.h>
#define log_vsnprintf vsnprintf #define log_vsnprintf vsnprintf
#define log_puts puts #define log_puts puts
#define log_exit scc_exit #define log_abort abort
#endif #endif
#ifdef __GNUC__ // GCC, Clang #ifdef __GNUC__ // GCC, Clang
@@ -37,9 +37,9 @@
#warning "log_puts not defined" #warning "log_puts not defined"
#endif #endif
#ifndef log_exit #ifndef log_abort
#define log_exit(...) #define log_abort(...)
#warning "log_exit not defined" #warning "log_abort not defined"
#endif #endif
/** /**
@@ -155,7 +155,7 @@ void log_set_handler(logger_t *logger, log_handler handler);
((void)((cond) || \ ((void)((cond) || \
(__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \ (__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \ &__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
log_exit(1), __scc_log_unreachable(), 0))) log_abort(), __scc_log_unreachable(), 0)))
/// @name 断言工具宏 /// @name 断言工具宏
/// @{ /// @{

View File

@@ -9,6 +9,7 @@
#define scc_realloc scc_pal_realloc #define scc_realloc scc_pal_realloc
#define scc_free scc_pal_free #define scc_free scc_pal_free
#define scc_exit scc_pal_exit #define scc_exit scc_pal_exit
#define scc_abort scc_pal_abort
typedef void *scc_file_t; typedef void *scc_file_t;
typedef enum { typedef enum {

View File

@@ -9,8 +9,8 @@
#define log_puts(str) scc_printf("%s", str) #define log_puts(str) scc_printf("%s", str)
#endif #endif
#ifndef log_exit #ifndef log_abort
#define log_exit scc_exit #define log_abort scc_abort
#endif #endif
#include <log.h> #include <log.h>

View File

@@ -17,6 +17,9 @@ void scc_pal_free(void *ptr);
// Required // Required
void scc_pal_exit(int code); void scc_pal_exit(int code);
// Option
void scc_pal_abort();
/* IO */ /* IO */
// Required // Required

View File

@@ -58,7 +58,7 @@
} \ } \
usize phys_tail = _scc_ring_phys(ring, (ring).tail); \ usize phys_tail = _scc_ring_phys(ring, (ring).tail); \
if ((ring).fill == null || \ if ((ring).fill == null || \
!(ring).fill(&(ring).data[phys_tail], (ring).userdata)) { \ !(ring).fill(&((ring).data[phys_tail]), (ring).userdata)) { \
ok = 0; \ ok = 0; \
break; \ break; \
} \ } \
@@ -104,7 +104,7 @@
#define scc_ring_init(ring, _cap, fill_func, _userdata) \ #define scc_ring_init(ring, _cap, fill_func, _userdata) \
do { \ do { \
(ring).data = \ (ring).data = \
(_cap) ? scc_malloc((_cap) * sizeof(*(ring).data)) : null; \ (_cap) != 0 ? scc_malloc((_cap) * sizeof(*(ring).data)) : null; \
(ring).cap = (_cap); \ (ring).cap = (_cap); \
(ring).head = 0; \ (ring).head = 0; \
(ring).probe = 0; \ (ring).probe = 0; \

View File

@@ -35,10 +35,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
/* clang-format off */
#ifndef PRINTF_H_ #ifndef PRINTF_H_
#define PRINTF_H_ #define PRINTF_H_
#define PRINTF_INCLUDE_CONFIG_H
#ifdef PRINTF_INCLUDE_CONFIG_H #ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h" #include "printf_config.h"
#endif #endif

View File

@@ -0,0 +1,10 @@
/* clang-format off */
/* Support for the decimal notation floating point conversion specifiers (%f, %F) */
#ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS
#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0
#endif
/* Support for the exponential notation floating point conversion specifiers (%e, %g, %E, %G) */
#ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0
#endif

View File

@@ -74,12 +74,15 @@ size_t scc_pal_fseek(scc_pal_file_t f, size_t offset,
void scc_pal_exit(int code) { exit(code); } void scc_pal_exit(int code) { exit(code); }
void scc_pal_abort() { abort(); }
void scc_pal_putchar(char c) { putchar(c); } void scc_pal_putchar(char c) { putchar(c); }
void scc_pal_eputchar(char c) { fputc(c, stderr); } void scc_pal_eputchar(char c) { fputc(c, stderr); }
void scc_pal_write(const char *data, size_t len) { void scc_pal_write(const char *data, size_t len) {
int res = fputs(data, stdout); int res = fputs(data, stdout);
(void)len; // FIXME maybe using len to check return value
if (res != 0) { if (res != 0) {
fprintf(stderr, "\nError writing to stdout [%d]\n", res); fprintf(stderr, "\nError writing to stdout [%d]\n", res);
scc_pal_exit(1); scc_pal_exit(1);
@@ -88,6 +91,7 @@ void scc_pal_write(const char *data, size_t len) {
void scc_pal_ewrite(const char *data, size_t len) { void scc_pal_ewrite(const char *data, size_t len) {
int res = fputs(data, stderr); int res = fputs(data, stderr);
(void)len; // FIXME maybe using len to check return value
if (res != 0) { if (res != 0) {
fprintf(stderr, "\nError writing to stderr [%d]\n", res); fprintf(stderr, "\nError writing to stderr [%d]\n", res);
scc_pal_exit(1); scc_pal_exit(1);

View File

@@ -5,13 +5,22 @@
#define __SCC_LOG_IMPL_IMPORT_SRC__ #define __SCC_LOG_IMPL_IMPORT_SRC__
#include <scc_core_log.h> #include <scc_core_log.h>
void putchar_(char ch) { LOG_FATAL("you can't use printf.c directly"); } void putchar_(char ch) {
(void)ch;
LOG_FATAL("you can't use printf.c directly");
}
scc_file_t scc_fopen(const char *path, scc_fmode_t mode) { scc_file_t scc_fopen(const char *path, scc_fmode_t mode) {
return scc_pal_fopen(path, (scc_pal_fmode_t)mode); // FIXME return scc_pal_fopen(path, (scc_pal_fmode_t)mode); // FIXME
} }
void scc_fclose(scc_file_t file) { scc_pal_fclose(file); } void scc_fclose(scc_file_t file) {
if (file == scc_stdout || file == scc_stderr) {
return;
} else {
scc_pal_fclose(file);
}
}
usize scc_fsize(scc_file_t file) { usize scc_fsize(scc_file_t file) {
if (scc_pal_fseek(file, 0, SCC_SEEK_PAL_END) != 0) { if (scc_pal_fseek(file, 0, SCC_SEEK_PAL_END) != 0) {