feat(parser): 实现赋值表达式和常量表达式解析功能
- 添加 scc_parse_assignment_expression 函数用于解析赋值表达式 - 添加 scc_parser_constant_expression 函数用于解析常量表达式 - 修改 cast 表达式解析逻辑,修复类型转换解析问题 - 改进错误处理机制,使用 SCC_ERROR 替代 LOG_ERROR 并提供准确位置信息 - 移除未使用的变量声明,优化代码结构 refactor(ast): 调整类型定义中的 typedef 类型存储结构 - 将 scc_ast_type 中的 underlying 字段改为 decl 字段 - 更新相关初始化函数以适配新的字段名称 - 修复枚举类型初始化时缺失的 decl 字段设置 feat(ast): 添加类型转换、sizeof 和 alignof 表达式的初始化函数 - 实现 scc_ast_expr_cast_init 用于初始化类型转换表达式 - 实现 scc_ast_expr_sizeof_init 用于初始化 sizeof 表达式 - 实现 scc_ast_expr_alignof_init 用于初始化 alignof 表达式 - 完善表达式类型的支持 chore(parser): 增加语义分析回调接口和位置获取工具函数 - 添加 scc_parse_decl_sema、scc_parse_type_sema 等语义分析辅助函数 - 提供 scc_parser_got_current_pos 函数获取当前解析位置 - 增强错误报告的准确性 refactor(dump): 完善 AST 转储功能,支持 break 和 continue 语句 - 为 SCC_AST_STMT_BREAK 和 SCC_AST_STMT_CONTINUE 添加转储支持 - 优化转储函数的分支处理结构
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user