From 5f915ba8d32eb828624c9aeb4f5d43bceaea89dd Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Wed, 18 Mar 2026 12:18:56 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ast):=20=E7=A7=BB=E9=99=A4=E5=86=85?= =?UTF-8?q?=E7=BD=AE=E7=B1=BB=E5=9E=8B=E5=A4=B4=E6=96=87=E4=BB=B6=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=B1=BB=E5=9E=8B=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了独立的ast_builtin.h头文件,将内置类型定义整合到现有结构中, 同时修复了类型初始化函数命名不一致的问题。 BREAKING CHANGE: 原有的ast_builtin.h头文件已被移除, 相关内置类型声明已重构为新的接口形式。 fix(parser): 修复表达式解析中的位置信息处理 确保条件表达式和逗号表达式的解析正确获取并传递位置信息, 避免在语法树构建过程中丢失源码位置。 refactor(ir): 修复IR转储中的类型转换问题 添加必要的类型转换以防止整数溢出,并优化代码格式以提高可读性。 feat(parser): 添加表达式解析测试套件 引入全面的表达式解析测试框架,覆盖从基本表达式到复杂嵌套表达式 的各种场景,确保解析器功能的正确性和稳定性。 --- libs/ast/include/ast_builtin.h | 31 - libs/ast/include/scc_ast.h | 7 +- libs/ast/src/ast_builtin.c | 128 --- libs/ir/src/ir_dump.c | 9 +- libs/parser/src/parse_expr.c | 8 +- libs/parser/src/parse_type.c | 10 +- libs/parser/src/scc_sema.c | 11 +- libs/parser/tests/gen_ast.h | 0 libs/parser/tests/parser_test.h | 95 ++ libs/parser/tests/test_parse_expr.c | 395 +++++++ libs/parser/tests/test_parse_type.c | 583 ++++++++++ libs/parser/tests/test_parser_unit.c | 1469 +++++--------------------- 12 files changed, 1376 insertions(+), 1370 deletions(-) delete mode 100644 libs/ast/include/ast_builtin.h delete mode 100644 libs/ast/src/ast_builtin.c create mode 100644 libs/parser/tests/gen_ast.h create mode 100644 libs/parser/tests/parser_test.h create mode 100644 libs/parser/tests/test_parse_expr.c create mode 100644 libs/parser/tests/test_parse_type.c diff --git a/libs/ast/include/ast_builtin.h b/libs/ast/include/ast_builtin.h deleted file mode 100644 index 544bd48..0000000 --- a/libs/ast/include/ast_builtin.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __SCC_AST_BUILTIN_H__ -#define __SCC_AST_BUILTIN_H__ - -#include "ast_def.h" - -extern scc_ast_type_t scc_ast_builtin_type_va_list; -extern scc_ast_type_t scc_ast_builtin_type_void; -extern scc_ast_type_t scc_ast_builtin_type_bool; -extern scc_ast_type_t scc_ast_builtin_type_char; -extern scc_ast_type_t scc_ast_builtin_type_short; -extern scc_ast_type_t scc_ast_builtin_type_long; -extern scc_ast_type_t scc_ast_builtin_type_long_long; -extern scc_ast_type_t scc_ast_builtin_type_int; -extern scc_ast_type_t scc_ast_builtin_type_float; -extern scc_ast_type_t scc_ast_builtin_type_double; -extern scc_ast_type_t scc_ast_builtin_type_long_double; -extern scc_ast_type_t scc_ast_builtin_type_complex_float; -extern scc_ast_type_t scc_ast_builtin_type_complex_double; -extern scc_ast_type_t scc_ast_builtin_type_complex_long_double; -extern scc_ast_type_t scc_ast_builtin_type_unsigned_char; -extern scc_ast_type_t scc_ast_builtin_type_unsigned_short; -extern scc_ast_type_t scc_ast_builtin_type_unsigned_int; -extern scc_ast_type_t scc_ast_builtin_type_unsigned_long; -extern scc_ast_type_t scc_ast_builtin_type_unsigned_long_long; -extern scc_ast_type_t scc_ast_builtin_type_signed_char; -extern scc_ast_type_t scc_ast_builtin_type_signed_short; -extern scc_ast_type_t scc_ast_builtin_type_signed_int; -extern scc_ast_type_t scc_ast_builtin_type_signed_long; -extern scc_ast_type_t scc_ast_builtin_type_signed_long_long; - -#endif diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index e188832..03e6b5b 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -1,7 +1,6 @@ #ifndef __SCC_AST_H__ #define __SCC_AST_H__ -#include "ast_builtin.h" #include "ast_def.h" #include "ast_dump.h" @@ -508,9 +507,9 @@ static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, } // have defined builtin type -static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type, - scc_ast_builtin_type_t builtin, - scc_pos_t loc) { +static inline void scc_ast_type_builtin_init(scc_ast_type_t *type, + scc_ast_builtin_type_t builtin, + scc_pos_t loc) { Assert(type != null); type->base.loc = loc; type->base.type = SCC_AST_TYPE_BUILTIN; diff --git a/libs/ast/src/ast_builtin.c b/libs/ast/src/ast_builtin.c deleted file mode 100644 index 9003a1b..0000000 --- a/libs/ast/src/ast_builtin.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#define SCC_AST_BUILTIN_TYPE_HEADER \ - .base.type = SCC_AST_TYPE_BUILTIN, .base.loc.col = 0, .base.loc.line = 0, \ - .base.loc.name = "__scc_ast_builtin_type", .base.loc.offset = 0 - -// va_list -scc_ast_type_t scc_ast_builtin_type_va_list = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_VA_LIST, -}; - -scc_ast_type_t scc_ast_builtin_type_void = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_VOID, -}; - -scc_ast_type_t scc_ast_builtin_type_bool = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_BOOL, -}; - -scc_ast_type_t scc_ast_builtin_type_char = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_CHAR, -}; - -scc_ast_type_t scc_ast_builtin_type_short = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SHORT, -}; - -scc_ast_type_t scc_ast_builtin_type_int = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_INT, -}; - -scc_ast_type_t scc_ast_builtin_type_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_LONG, -}; - -scc_ast_type_t scc_ast_builtin_type_long_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_LONG_LONG, -}; - -// unsigned 类型 -scc_ast_type_t scc_ast_builtin_type_unsigned_char = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR, -}; - -scc_ast_type_t scc_ast_builtin_type_unsigned_short = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT, -}; - -scc_ast_type_t scc_ast_builtin_type_unsigned_int = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_INT, -}; - -scc_ast_type_t scc_ast_builtin_type_unsigned_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, -}; - -scc_ast_type_t scc_ast_builtin_type_unsigned_long_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG, -}; - -// signed 类型(实际上与默认相同,但为了完整性) -scc_ast_type_t scc_ast_builtin_type_signed_char = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_CHAR, -}; - -scc_ast_type_t scc_ast_builtin_type_signed_short = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_SHORT, -}; - -scc_ast_type_t scc_ast_builtin_type_signed_int = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_INT, -}; - -scc_ast_type_t scc_ast_builtin_type_signed_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG, -}; - -scc_ast_type_t scc_ast_builtin_type_signed_long_long = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG, -}; - -scc_ast_type_t scc_ast_builtin_type_float = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_FLOAT, -}; - -scc_ast_type_t scc_ast_builtin_type_double = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_DOUBLE, -}; - -scc_ast_type_t scc_ast_builtin_type_long_double = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_LONG_DOUBLE, -}; - -scc_ast_type_t scc_ast_builtin_type_complex_float = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT, -}; - -scc_ast_type_t scc_ast_builtin_type_complex_double = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE, -}; - -scc_ast_type_t scc_ast_builtin_type_complex_long_double = { - SCC_AST_BUILTIN_TYPE_HEADER, - .builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE, -}; diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index 69d88f8..f5fa5d6 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -21,7 +21,7 @@ static const char *get_node_type_str(scc_ir_node_tag_t tag) { [SCC_IR_NODE_RET] = "Return", }; - if (tag >= 0 && tag < sizeof(node_types) / sizeof(node_types[0]) && + if (tag >= 0 && (usize)tag < sizeof(node_types) / sizeof(node_types[0]) && node_types[tag] != NULL) { return node_types[tag]; } @@ -39,11 +39,12 @@ static const char *get_op_str(scc_ir_op_type_t op) { [SCC_IR_OP_DIV] = "/", [SCC_IR_OP_MOD] = "%", [SCC_IR_OP_AND] = "&", [SCC_IR_OP_OR] = "|", [SCC_IR_OP_XOR] = "^", [SCC_IR_OP_NOT] = "~", - [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>", + [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>", [SCC_IR_OP_SAR] = ">>a", // Arithmetic shift right }; - if (op >= 0 && op < sizeof(ops) / sizeof(ops[0]) && ops[op] != NULL) { + if (op >= 0 && (usize)op < sizeof(ops) / sizeof(ops[0]) && + ops[op] != NULL) { return ops[op]; } return ""; @@ -64,7 +65,7 @@ static const char *get_type_tag_str(scc_ir_type_tag_t tag) { [SCC_IR_TYPE_STRUCT] = "struct", [SCC_IR_TYPE_VECTOR] = "vector", }; - if (tag >= 0 && tag < sizeof(type_tags) / sizeof(type_tags[0]) && + if (tag >= 0 && (usize)tag < sizeof(type_tags) / sizeof(type_tags[0]) && type_tags[tag] != NULL) { return type_tags[tag]; } diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 01dbe5e..ca22867 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -427,8 +427,8 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { return null; const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); - scc_pos_t pos = tok_ptr->loc; if (tok_ptr && tok_ptr->type == SCC_TOK_COND) { + scc_pos_t pos = tok_ptr->loc; // 消耗 '?' scc_lexer_tok_t q_tok; if (!scc_parser_next_consume(parser, &q_tok)) @@ -867,6 +867,9 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) { break; } + scc_pos_t pos = tok_ptr->loc; + scc_parser_next_consume(parser, null); + scc_ast_expr_t *right = scc_parse_assignment_expression(parser); if (!right) { parser_sync(parser); @@ -874,8 +877,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, - tok_ptr->loc); + scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos); left = expr; } return left; diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index c671027..e91c933 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -529,7 +529,7 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info, } scc_ast_type_t *type = ast_type_alloc(); - _scc_ast_type_builtin_init(type, builtin, pos); + scc_ast_type_builtin_init(type, builtin, pos); // 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责 return type; } @@ -930,8 +930,12 @@ static void parse_parameter_type_list(scc_parser_t *parser, param = scc_malloc(sizeof(scc_ast_decl_t)); Assert(param != null); // FIXME - scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null, - tok_ptr->loc); + type = scc_malloc(sizeof(scc_ast_type_t)); + Assert(type != null); + scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST, + tok_ptr->loc); + scc_ast_decl_param_init(param, type, null, tok_ptr->loc); + scc_parser_next_consume(parser, null); scc_vec_push(*params, param); break; } diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index a4ef18f..434a371 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -117,12 +117,13 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) { callbacks->got_type = got_type_callback; scc_sema_symtab_init(sema_symtab); + + // FIXME memory leak + scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); + scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST, + scc_pos_create()); 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); + &type->base); } void scc_sema_drop(scc_sema_callbacks_t *callbacks) {} diff --git a/libs/parser/tests/gen_ast.h b/libs/parser/tests/gen_ast.h new file mode 100644 index 0000000..e69de29 diff --git a/libs/parser/tests/parser_test.h b/libs/parser/tests/parser_test.h new file mode 100644 index 0000000..6f3e76d --- /dev/null +++ b/libs/parser/tests/parser_test.h @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + +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, + cbool need_sema) { + int res = 0; + scc_sstream_t mem_stream; + res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(res == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); + + scc_parser_t parser; + 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); + + cbool not_eof = false; + scc_ring_not_eof(*parser.ring, not_eof); + if (not_eof == true) { + // FIXME MAYBE free + LOG_ERROR("Didn't consume all tokens"); + return null; + } + + scc_lexer_drop_ring(parser.ring); + scc_parser_drop(&parser); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); + return ret; +} + +typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); + +#define BUFFER_SIZE (4096) +char expect_buffer[BUFFER_SIZE]; +char output_buffer[BUFFER_SIZE]; + +static void dump2buffer(void *_buffer, const char *fmt, ...) { + char *buffer = _buffer; + va_list args; + va_start(args, fmt); + int res = scc_vsnprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer) - 1, fmt, args); + Assert(res > 0); + va_end(args); +} + +static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, + 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); + scc_ast_dump_node(&ctx, expect_node_ptr); + scc_tree_dump_ctx_drop(&ctx); + output_buffer[0] = '\n', output_buffer[1] = '\0'; + scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); + scc_ast_dump_node(&ctx, output_node_ptr); + 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, \ + false); \ + TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ + TEST_MSG("Expected: %s", expect_buffer); \ + TEST_MSG("Produced: %s", output_buffer); \ + } while (0); diff --git a/libs/parser/tests/test_parse_expr.c b/libs/parser/tests/test_parse_expr.c new file mode 100644 index 0000000..cbe59b4 --- /dev/null +++ b/libs/parser/tests/test_parse_expr.c @@ -0,0 +1,395 @@ +void init_func(void); +#define TEST_INIT init_func() + +#include "parser_test.h" + +static scc_ast_type_t int_type; +void init_func(void) { + scc_ast_type_builtin_init(&int_type, SCC_AST_BUILTIN_TYPE_INT, + scc_pos_create()); +} + +#define LOC scc_pos_create() + +static void test_primary_expr(void) { + TEST_CASE("identifier"); + { + scc_ast_expr_t ident; + scc_ast_expr_identifier_init(&ident, "x", LOC); + SCC_CHECK_AST(&ident.base, "x", scc_parse_expression); + } + + TEST_CASE("integer literal"); + { + scc_ast_expr_t int_lit; + scc_ast_expr_literal_int_init(&int_lit, "42", false, LOC); + SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression); + } + + TEST_CASE("string literal"); + { + scc_ast_expr_t str_lit; + scc_ast_expr_literal_string_init(&str_lit, "\"hello\"", false, LOC); + SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression); + } + + TEST_CASE("parenthesized expression"); + { + scc_ast_expr_t ident; + scc_ast_expr_identifier_init(&ident, "y", LOC); + // 解析器应直接返回内部表达式,因此期望结果与 "y" 相同 + SCC_CHECK_AST(&ident.base, "(y)", scc_parse_expression); + } +} + +static void test_postfix_expr(void) { + TEST_CASE("array subscript"); + { + scc_ast_expr_t a, index, subscript; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_literal_int_init(&index, "10", false, LOC); + scc_ast_expr_array_subscript_init(&subscript, &a, &index, LOC); + SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); + } + + TEST_CASE("function call (no arguments)"); + { + scc_ast_expr_t callee, call; + scc_ast_expr_identifier_init(&callee, "f", LOC); + scc_ast_expr_vec_t args; + scc_vec_init(args); + scc_ast_expr_call_init(&call, &callee, &args, LOC); + SCC_CHECK_AST(&call.base, "f()", scc_parse_expression); + } + + TEST_CASE("function call (with arguments)"); + { + scc_ast_expr_t callee, arg1, arg2, call; + scc_ast_expr_identifier_init(&callee, "f", LOC); + scc_ast_expr_literal_int_init(&arg1, "1", false, LOC); + scc_ast_expr_identifier_init(&arg2, "x", LOC); + + scc_ast_expr_vec_t args; + scc_vec_init(args); + scc_vec_push(args, &arg1); + scc_vec_push(args, &arg2); + + scc_ast_expr_call_init(&call, &callee, &args, LOC); + SCC_CHECK_AST(&call.base, "f(1, x)", scc_parse_expression); + } + + TEST_CASE("member access (.)"); + { + scc_ast_expr_t obj, member; + scc_ast_expr_identifier_init(&obj, "s", LOC); + scc_ast_expr_member_init(&member, &obj, "field", LOC); + SCC_CHECK_AST(&member.base, "s.field", scc_parse_expression); + } + + TEST_CASE("pointer member access (->)"); + { + scc_ast_expr_t ptr, member; + scc_ast_expr_identifier_init(&ptr, "p", LOC); + scc_ast_expr_ptr_member_init(&member, &ptr, "field", LOC); + SCC_CHECK_AST(&member.base, "p->field", scc_parse_expression); + } + + TEST_CASE("postfix increment/decrement"); + { + scc_ast_expr_t x, post_inc, post_dec; + scc_ast_expr_identifier_init(&x, "x", LOC); + scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &x, + LOC); + scc_ast_expr_unary_init(&post_dec, SCC_AST_OP_POSTFIX_DECREMENT, &x, + LOC); + SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression); + SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression); + } +} + +static void test_unary_expr(void) { + scc_ast_expr_t x; + scc_ast_expr_identifier_init(&x, "x", LOC); + + TEST_CASE("prefix increment"); + { + scc_ast_expr_t pre_inc; + scc_ast_expr_unary_init(&pre_inc, SCC_AST_OP_PREFIX_INCREMENT, &x, LOC); + SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression); + } + + TEST_CASE("prefix decrement"); + { + scc_ast_expr_t pre_dec; + scc_ast_expr_unary_init(&pre_dec, SCC_AST_OP_PREFIX_DECREMENT, &x, LOC); + SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression); + } + + TEST_CASE("address-of"); + { + scc_ast_expr_t addr; + scc_ast_expr_unary_init(&addr, SCC_AST_OP_ADDRESS_OF, &x, LOC); + SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression); + } + + TEST_CASE("indirection (dereference)"); + { + scc_ast_expr_t deref; + scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &x, LOC); + SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression); + } + + TEST_CASE("unary plus"); + { + scc_ast_expr_t plus; + scc_ast_expr_unary_init(&plus, SCC_AST_OP_UNARY_PLUS, &x, LOC); + SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression); + } + + TEST_CASE("unary minus"); + { + scc_ast_expr_t minus; + scc_ast_expr_unary_init(&minus, SCC_AST_OP_UNARY_MINUS, &x, LOC); + SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression); + } + + TEST_CASE("bitwise NOT"); + { + scc_ast_expr_t bit_not; + scc_ast_expr_unary_init(&bit_not, SCC_AST_OP_BITWISE_NOT, &x, LOC); + SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression); + } + + TEST_CASE("logical NOT"); + { + scc_ast_expr_t log_not; + scc_ast_expr_unary_init(&log_not, SCC_AST_OP_LOGICAL_NOT, &x, LOC); + SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression); + } + + TEST_CASE("sizeof expression"); + { + scc_ast_expr_t sizeof_expr; + scc_ast_expr_sizeof_init(&sizeof_expr, NULL, &x, LOC); + SCC_CHECK_AST(&sizeof_expr.base, "sizeof(x)", scc_parse_expression); + } + + TEST_CASE("sizeof type"); + { + scc_ast_expr_t sizeof_type; + scc_ast_expr_sizeof_init(&sizeof_type, &int_type, NULL, LOC); + SCC_CHECK_AST(&sizeof_type.base, "sizeof(int)", scc_parse_expression); + } +} + +static void test_cast_expr(void) { + TEST_CASE("cast"); + { + scc_ast_expr_t x, cast; + scc_ast_expr_identifier_init(&x, "x", LOC); + scc_ast_expr_cast_init(&cast, &int_type, &x, LOC); + SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); + } +} + +static void test_binary_expr(void) { + scc_ast_expr_t a, b, c, d; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_identifier_init(&b, "b", LOC); + scc_ast_expr_identifier_init(&c, "c", LOC); + scc_ast_expr_identifier_init(&d, "d", LOC); + + TEST_CASE("multiplication and addition (priority)"); + { + // a * b + c + scc_ast_expr_t mul, add; + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &a, &b, LOC); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &mul, &c, LOC); + SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression); + } + + TEST_CASE("subtraction (left associativity)"); + { + // a - b - c => (a - b) - c + scc_ast_expr_t sub1, sub2; + scc_ast_expr_binary_init(&sub1, SCC_AST_OP_SUB, &a, &b, LOC); + scc_ast_expr_binary_init(&sub2, SCC_AST_OP_SUB, &sub1, &c, LOC); + SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression); + } + + TEST_CASE("shift"); + { + // a << b + scc_ast_expr_t shift; + scc_ast_expr_binary_init(&shift, SCC_AST_OP_LEFT_SHIFT, &a, &b, LOC); + SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression); + } + + TEST_CASE("relational"); + { + // a < b + scc_ast_expr_t lt; + scc_ast_expr_binary_init(<, SCC_AST_OP_LESS, &a, &b, LOC); + SCC_CHECK_AST(<.base, "a < b", scc_parse_expression); + } + + TEST_CASE("equality"); + { + // a == b + scc_ast_expr_t eq; + scc_ast_expr_binary_init(&eq, SCC_AST_OP_EQUAL, &a, &b, LOC); + SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression); + } + + TEST_CASE("bitwise operators (priority)"); + { + // a & b ^ c | d => ((a & b) ^ c) | d + scc_ast_expr_t bitand, bitxor, bitor; + scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b, LOC); + scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c, + LOC); + scc_ast_expr_binary_init(&bitor, SCC_AST_OP_BITWISE_OR, &bitxor, &d, + LOC); + SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression); + } + + TEST_CASE("logical operators (priority)"); + { + // a && b || c => (a && b) || c + scc_ast_expr_t logand, logor; + scc_ast_expr_binary_init(&logand, SCC_AST_OP_LOGICAL_AND, &a, &b, LOC); + scc_ast_expr_binary_init(&logor, SCC_AST_OP_LOGICAL_OR, &logand, &c, + LOC); + SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression); + } +} + +static void test_conditional_expr(void) { + scc_ast_expr_t a, b, c; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_identifier_init(&b, "b", LOC); + scc_ast_expr_identifier_init(&c, "c", LOC); + + TEST_CASE("simple conditional"); + { + scc_ast_expr_t cond; + scc_ast_expr_cond_init(&cond, &a, &b, &c, LOC); + SCC_CHECK_AST(&cond.base, "a ? b : c", scc_parse_expression); + } + + TEST_CASE("nested conditional (right associative)"); + { + // a ? b : c ? d : e => a ? b : (c ? d : e) + scc_ast_expr_t d, e, inner, outer; + scc_ast_expr_identifier_init(&d, "d", LOC); + scc_ast_expr_identifier_init(&e, "e", LOC); + scc_ast_expr_cond_init(&inner, &c, &d, &e, LOC); + scc_ast_expr_cond_init(&outer, &a, &b, &inner, LOC); + SCC_CHECK_AST(&outer.base, "a ? b : c ? d : e", scc_parse_expression); + } +} + +static void test_assignment_expr(void) { + scc_ast_expr_t a, b, c; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_identifier_init(&b, "b", LOC); + scc_ast_expr_identifier_init(&c, "c", LOC); + scc_ast_expr_t lit42; + scc_ast_expr_literal_int_init(&lit42, "42", false, LOC); + + TEST_CASE("simple assignment"); + { + // a = 42 + scc_ast_expr_t assign; + scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &a, &lit42, LOC); + SCC_CHECK_AST(&assign.base, "a = 42", scc_parse_expression); + } + + TEST_CASE("chained assignment (right associative)"); + { + // a = b = c + scc_ast_expr_t inner, outer; + scc_ast_expr_binary_init(&inner, SCC_AST_OP_ASSIGN, &b, &c, LOC); + scc_ast_expr_binary_init(&outer, SCC_AST_OP_ASSIGN, &a, &inner, LOC); + SCC_CHECK_AST(&outer.base, "a = b = c", scc_parse_expression); + } + + TEST_CASE("compound assignment"); + { + // a += b + scc_ast_expr_t add_assign; + scc_ast_expr_binary_init(&add_assign, SCC_AST_OP_ASSIGN_ADD, &a, &b, + LOC); + SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression); + } + + TEST_CASE("assignment with expression"); + { + // a = a - b + 42 + scc_ast_expr_t sub, add, assign; + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a, &b, LOC); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &sub, &lit42, LOC); + scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &a, &add, LOC); + SCC_CHECK_AST(&assign.base, "a = a - b + 42", scc_parse_expression); + } +} + +static void test_comma_expr(void) { + TEST_CASE("comma operator"); + { + scc_ast_expr_t a, b, comma; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_identifier_init(&b, "b", LOC); + scc_ast_expr_binary_init(&comma, SCC_AST_OP_COMMA, &a, &b, LOC); + SCC_CHECK_AST(&comma.base, "a, b", scc_parse_expression); + } +} + +static void test_complex_expr(void) { + TEST_CASE("mixed operators with precedence"); + { + scc_ast_expr_t a, b, c, d; + scc_ast_expr_identifier_init(&a, "a", LOC); + scc_ast_expr_identifier_init(&b, "b", LOC); + scc_ast_expr_identifier_init(&c, "c", LOC); + scc_ast_expr_identifier_init(&d, "d", LOC); + + // a + b * c - d + scc_ast_expr_t mul, add, sub; + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c, LOC); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &a, &mul, LOC); + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &add, &d, LOC); + SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression); + } + + TEST_CASE("postfix and unary combination"); + { + scc_ast_expr_t p, post_inc, deref; + scc_ast_expr_identifier_init(&p, "p", LOC); + scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &p, + LOC); + scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &post_inc, LOC); + SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression); + } +} + +static void test_detail_expr(void) { + TEST_CASE("multi string literal connection"); + scc_ast_expr_t str; + scc_ast_expr_literal_string_init(&str, "\"ab\"", false, scc_pos_create()); + SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression); +} + +TEST_LIST = { + {"test_primary_expr", test_primary_expr}, + {"test_postfix_expr", test_postfix_expr}, + {"test_unary_expr", test_unary_expr}, + {"test_cast_expr", test_cast_expr}, + {"test_binary_expr", test_binary_expr}, + {"test_conditional_expr", test_conditional_expr}, + {"test_assignment_expr", test_assignment_expr}, + {"test_comma_expr", test_comma_expr}, + {"test_complex_expr", test_complex_expr}, + {"test_detail_expr", test_detail_expr}, + {NULL, NULL}, +}; diff --git a/libs/parser/tests/test_parse_type.c b/libs/parser/tests/test_parse_type.c new file mode 100644 index 0000000..8e4217d --- /dev/null +++ b/libs/parser/tests/test_parse_type.c @@ -0,0 +1,583 @@ +void init_func(void); +#define TEST_INIT init_func() + +#include "parser_test.h" + +static scc_ast_type_t int_type; +static scc_ast_type_t char_type; +static scc_ast_type_t void_type; +static scc_ast_type_t pointer_int_type; +static scc_ast_type_t pointer_char_type; +static scc_ast_type_t pointer_void_type; +static scc_ast_type_t pointer_pointer_int_type; + +void init_func(void) { + scc_ast_type_builtin_init(&int_type, SCC_AST_BUILTIN_TYPE_INT, + scc_pos_create()); + scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, + scc_pos_create()); + scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, + scc_pos_create()); + scc_ast_type_pointer_init(&pointer_int_type, &int_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_char_type, &char_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_void_type, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_pointer_int_type, &pointer_int_type, + scc_pos_create()); +} + +static void test_builtin_type(void) { +#define CHECK_BUILTIN_TYPE(type, str) \ + do { \ + scc_ast_type_t builtin_type; \ + scc_ast_type_builtin_init(&builtin_type, type, scc_pos_create()); \ + SCC_CHECK_AST(&builtin_type.base, str, scc_parse_type_name); \ + } while (0) + + // CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_VA_LIST, "..."); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_VOID, "void"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_BOOL, "bool"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_CHAR, "char"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SHORT, "short"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_INT, "int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_LONG, "long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_LONG, "long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_LONG_LONG, "long long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_LONG_LONG, "long long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR, "unsigned char"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT, "unsigned short"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_INT, "unsigned int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, "unsigned long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, "unsigned long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG, + "unsigned long long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG, + "unsigned long long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_CHAR, "signed char"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_SHORT, "signed short"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_INT, "signed int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG, "signed long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG, "signed long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG, + "signed long long"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG, + "signed long long int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_FLOAT, "float"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_DOUBLE, "double"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_LONG_DOUBLE, "long double"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT, "complex float"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE, "complex double"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE, + "complex long double"); +#undef CHECK_BUILTIN_TYPE +} + +static void test_pointer_type(void) { + TEST_CASE("simple pointer"); + // int * + SCC_CHECK_AST(&pointer_int_type.base, "int *", scc_parse_type_name); + // int ** + SCC_CHECK_AST(&pointer_pointer_int_type.base, "int **", + scc_parse_type_name); + // int *** (需要临时构建) + { + scc_ast_type_t ptr_ptr_ptr_int; + scc_ast_type_pointer_init(&ptr_ptr_ptr_int, &pointer_pointer_int_type, + scc_pos_create()); + SCC_CHECK_AST(&ptr_ptr_ptr_int.base, "int ***", scc_parse_type_name); + } +} + +static void test_array_type(void) { + scc_ast_expr_t size_5, size_3; + + TEST_CASE("fixed size array"); + { + // int [5] + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + scc_ast_type_t array_5_int; + scc_ast_type_array_init(&array_5_int, &int_type, &size_5, + scc_pos_create()); + SCC_CHECK_AST(&array_5_int.base, "int [5]", scc_parse_type_name); + } + + TEST_CASE("incomplete array"); + { + // int [] + scc_ast_type_t array_unknown_int; + scc_ast_type_array_init(&array_unknown_int, &int_type, NULL, + scc_pos_create()); + SCC_CHECK_AST(&array_unknown_int.base, "int []", scc_parse_type_name); + } + + TEST_CASE("multidimensional array"); + { + // int [5][3] + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&size_3, "3", false, scc_pos_create()); + + scc_ast_type_t inner_array; + scc_ast_type_array_init(&inner_array, &int_type, &size_3, + scc_pos_create()); + + scc_ast_type_t outer_array; + scc_ast_type_array_init(&outer_array, &inner_array, &size_5, + scc_pos_create()); + SCC_CHECK_AST(&outer_array.base, "int [5][3]", scc_parse_type_name); + } + + TEST_CASE("pointer to array"); + { + // int (*)[5] + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + + scc_ast_type_t array_5_int; + scc_ast_type_array_init(&array_5_int, &int_type, &size_5, + scc_pos_create()); + + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_5_int, + scc_pos_create()); + SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", scc_parse_type_name); + } + + TEST_CASE("array of pointers"); + { + // int *[5] + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + + scc_ast_type_t array_of_ptr; + scc_ast_type_array_init(&array_of_ptr, &pointer_int_type, &size_5, + scc_pos_create()); + SCC_CHECK_AST(&array_of_ptr.base, "int *[5]", scc_parse_type_name); + } +} + +static void test_function_type(void) { + TEST_CASE("function with no parameters (old-style)"); + { + // int () + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, NULL, + scc_pos_create()); + SCC_CHECK_AST(&func_type.base, "int ()", scc_parse_type_name); + } + + TEST_CASE("function with void parameter"); + { + // int (void) + scc_ast_decl_t void_param; + scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_pos_create()); + + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, &void_param); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + SCC_CHECK_AST(&func_type.base, "int (void)", scc_parse_type_name); + } + + TEST_CASE("function with parameters"); + { + // int (int, float) + scc_ast_type_t float_type; + scc_ast_type_builtin_init(&float_type, SCC_AST_BUILTIN_TYPE_FLOAT, + scc_pos_create()); + + scc_ast_decl_t param_int, param_float; + scc_ast_decl_param_init(¶m_int, &int_type, NULL, scc_pos_create()); + scc_ast_decl_param_init(¶m_float, &float_type, NULL, + scc_pos_create()); + + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, ¶m_int); + scc_vec_push(params, ¶m_float); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + SCC_CHECK_AST(&func_type.base, "int (int, float)", scc_parse_type_name); + } + + TEST_CASE("function with variadic parameters"); + { + // int (int, ...) + scc_ast_type_t va_list_type; + scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST, + scc_pos_create()); + + scc_ast_decl_t param_int, param_var; + scc_ast_decl_param_init(¶m_int, &int_type, NULL, scc_pos_create()); + scc_ast_decl_param_init(¶m_var, &va_list_type, "...", + scc_pos_create()); + + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, ¶m_int); + scc_vec_push(params, ¶m_var); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + SCC_CHECK_AST(&func_type.base, "int (int, ...)", scc_parse_type_name); + } + + TEST_CASE("function returning pointer"); + { + // int *() + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &pointer_int_type, NULL, + scc_pos_create()); + SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name); + } + + TEST_CASE("pointer to function"); + { + // int (*)(void) + scc_ast_decl_t void_param; + scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_pos_create()); + + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, &void_param); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", scc_parse_type_name); + } +} + +static void test_struct_union_type(void) { + TEST_CASE("struct tag (incomplete)"); + { + // struct S + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, "S", NULL, scc_pos_create()); + SCC_CHECK_AST(&struct_type.base, "struct S", scc_parse_type_name); + } + + TEST_CASE("union tag (incomplete)"); + { + // union U + scc_ast_type_t union_type; + scc_ast_type_union_init(&union_type, "U", NULL, scc_pos_create()); + SCC_CHECK_AST(&union_type.base, "union U", scc_parse_type_name); + } + + TEST_CASE("anonymous struct definition"); + { + // struct { int x; } + scc_ast_decl_t field_x; + scc_ast_decl_val_init(&field_x, &int_type, "x", NULL, scc_pos_create()); + + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field_x); + + scc_ast_decl_t struct_decl; + scc_ast_decl_struct_init(&struct_decl, NULL, &fields, scc_pos_create()); + + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, NULL, &struct_decl, + scc_pos_create()); + SCC_CHECK_AST(&struct_type.base, "struct { int x; }", + scc_parse_type_name); + } + + TEST_CASE("named struct definition"); + { + // struct S { int x; } + scc_ast_decl_t field_x; + scc_ast_decl_val_init(&field_x, &int_type, "x", NULL, scc_pos_create()); + + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field_x); + + scc_ast_decl_t struct_decl; + scc_ast_decl_struct_init(&struct_decl, "S", &fields, scc_pos_create()); + + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, "S", &struct_decl, + scc_pos_create()); + SCC_CHECK_AST(&struct_type.base, "struct S { int x; }", + scc_parse_type_name); + } + + TEST_CASE("union definition"); + { + // union { int a; float b; } + scc_ast_type_t float_type; + scc_ast_type_builtin_init(&float_type, SCC_AST_BUILTIN_TYPE_FLOAT, + scc_pos_create()); + + scc_ast_decl_t field_a, field_b; + scc_ast_decl_val_init(&field_a, &int_type, "a", NULL, scc_pos_create()); + scc_ast_decl_val_init(&field_b, &float_type, "b", NULL, + scc_pos_create()); + + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field_a); + scc_vec_push(fields, &field_b); + + scc_ast_decl_t union_decl; + scc_ast_decl_union_init(&union_decl, NULL, &fields, scc_pos_create()); + + scc_ast_type_t union_type; + scc_ast_type_union_init(&union_type, NULL, &union_decl, + scc_pos_create()); + SCC_CHECK_AST(&union_type.base, "union { int a; float b; }", + scc_parse_type_name); + } +} + +static void test_enum_type(void) { + TEST_CASE("enum tag (incomplete)"); + { + // enum E + scc_ast_type_t enum_type; + scc_ast_type_enum_init(&enum_type, "E", NULL, scc_pos_create()); + SCC_CHECK_AST(&enum_type.base, "enum E", scc_parse_type_name); + } + + TEST_CASE("anonymous enum definition"); + { + // enum { RED, GREEN, BLUE } + scc_ast_expr_t red, green, blue; + scc_ast_expr_identifier_init(&red, "RED", scc_pos_create()); + scc_ast_expr_identifier_init(&green, "GREEN", scc_pos_create()); + scc_ast_expr_identifier_init(&blue, "BLUE", scc_pos_create()); + + 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_decl_t enum_decl; + scc_ast_decl_enum_init(&enum_decl, NULL, &enumerators, + scc_pos_create()); + + scc_ast_type_t enum_type; + scc_ast_type_enum_init(&enum_type, NULL, &enum_decl, scc_pos_create()); + SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", + scc_parse_type_name); + } + + TEST_CASE("named enum definition"); + { + // enum E { RED, GREEN, BLUE } + scc_ast_expr_t red, green, blue; + scc_ast_expr_identifier_init(&red, "RED", scc_pos_create()); + scc_ast_expr_identifier_init(&green, "GREEN", scc_pos_create()); + scc_ast_expr_identifier_init(&blue, "BLUE", scc_pos_create()); + + 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_decl_t enum_decl; + scc_ast_decl_enum_init(&enum_decl, "E", &enumerators, scc_pos_create()); + + scc_ast_type_t enum_type; + scc_ast_type_enum_init(&enum_type, "E", &enum_decl, scc_pos_create()); + SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE }", + scc_parse_type_name); + } +} + +static void test_specifier_type(void) { + TEST_CASE("const/volatile on builtin types"); + { + // const int + scc_ast_type_t const_int = int_type; + const_int.quals.is_const = true; + SCC_CHECK_AST(&const_int.base, "const int", scc_parse_type_name); + + // volatile int + scc_ast_type_t volatile_int = int_type; + volatile_int.quals.is_volatile = true; + SCC_CHECK_AST(&volatile_int.base, "volatile int", scc_parse_type_name); + + // const volatile int + scc_ast_type_t const_volatile_int = int_type; + const_volatile_int.quals.is_const = true; + const_volatile_int.quals.is_volatile = true; + SCC_CHECK_AST(&const_volatile_int.base, "const volatile int", + scc_parse_type_name); + } + + TEST_CASE("const/volatile on pointers"); + { + // int * const (const pointer to int) + scc_ast_type_t const_ptr_to_int = pointer_int_type; + const_ptr_to_int.quals.is_const = true; + SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", + scc_parse_type_name); + + // const int * (pointer to const int) + scc_ast_type_t const_int = int_type; + const_int.quals.is_const = true; + scc_ast_type_t ptr_to_const_int; + scc_ast_type_pointer_init(&ptr_to_const_int, &const_int, + scc_pos_create()); + SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", + scc_parse_type_name); + + // const int * const (const pointer to const int) + scc_ast_type_t const_ptr_to_const_int; + scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int, + scc_pos_create()); + const_ptr_to_const_int.quals.is_const = true; + SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const", + scc_parse_type_name); + + // volatile int * restrict (restrict pointer to volatile int) + scc_ast_type_t volatile_int = int_type; + volatile_int.quals.is_volatile = true; + scc_ast_type_t restrict_ptr_to_volatile_int; + scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int, + scc_pos_create()); + restrict_ptr_to_volatile_int.quals.is_restrict = true; + SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base, + "volatile int * restrict", scc_parse_type_name); + } + + TEST_CASE("const on array element type"); + { + // const int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + + scc_ast_type_t const_int = int_type; + const_int.quals.is_const = true; + + scc_ast_type_t const_array; + scc_ast_type_array_init(&const_array, &const_int, &size_5, + scc_pos_create()); + SCC_CHECK_AST(&const_array.base, "const int [5]", scc_parse_type_name); + } +} + +static void test_hard_type(void) { + TEST_CASE("pointer to array of pointers to function"); + // int (*(*)[5])(void) + { + // 1) 函数类型 int (void) + scc_ast_decl_t void_param; + scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_pos_create()); + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, &void_param); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + + // 2) 指向函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + + // 3) 数组,元素为上述指针,大小5 + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + + scc_ast_type_t array_of_ptr; + scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, &size_5, + scc_pos_create()); + + // 4) 指向数组的指针 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr, + scc_pos_create()); + + SCC_CHECK_AST(&ptr_to_array.base, "int (*(*)[5])(void)", + scc_parse_type_name); + } + + TEST_CASE("pointer to function returning pointer to array"); + // int (*(*)(void))[5] + { + // 1) 数组类型 int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + + scc_ast_type_t array_type; + scc_ast_type_array_init(&array_type, &int_type, &size_5, + scc_pos_create()); + + // 2) 指向数组的指针 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_type, scc_pos_create()); + + // 3) 函数类型,返回上述指针,无参数 + scc_ast_decl_t void_param; + scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_pos_create()); + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, &void_param); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &ptr_to_array, ¶ms, + scc_pos_create()); + + // 4) 指向函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + + SCC_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]", + scc_parse_type_name); + } + + TEST_CASE("function returning pointer to function"); + // int (*())(void) + { + // 1) 函数类型 int (void) + scc_ast_decl_t void_param; + scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_pos_create()); + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, &void_param); + + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &int_type, ¶ms, + scc_pos_create()); + + // 2) 指向该函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + + // 3) 外部函数类型,返回上述指针,无参数 + scc_ast_type_t outer_func; + scc_ast_type_function_init(&outer_func, &ptr_to_func, NULL, + scc_pos_create()); + + SCC_CHECK_AST(&outer_func.base, "int (*())(void)", scc_parse_type_name); + } +} + +TEST_LIST = { + {"test_builtin_type", test_builtin_type}, + {"test_pointer_type", test_pointer_type}, + {"test_array_type", test_array_type}, + {"test_function_type", test_function_type}, + {"test_struct_union_type", test_struct_union_type}, + {"test_enum_type", test_enum_type}, + {"test_specifier_type", test_specifier_type}, + {"test_hard_type", test_hard_type}, + {NULL, NULL}, +}; diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index 035d00e..8c87ec0 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -1,106 +1,39 @@ -#include -#include -#include -#include -#include -#include +void init_func(void); +#define TEST_INIT init_func() -typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); +#include "parser_test.h" -static scc_ast_node_t *process_input(const char *input, - 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, - 16); - Assert(res == 0); +static scc_ast_type_t int_type; +static scc_ast_type_t char_type; +static scc_ast_type_t void_type; +static scc_ast_type_t pointer_int_type; +static scc_ast_type_t pointer_char_type; +static scc_ast_type_t pointer_void_type; +static scc_ast_type_t pointer_pointer_int_type; +static scc_ast_type_t va_list_type; - scc_lexer_t lexer; - scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); - - scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); - - scc_parser_t parser; - 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); - - cbool not_eof = false; - scc_ring_not_eof(*parser.ring, not_eof); - if (not_eof == true) { - // FIXME MAYBE free - LOG_ERROR("Didn't consume all tokens"); - return null; - } - - scc_lexer_drop_ring(parser.ring); - scc_parser_drop(&parser); - scc_lexer_drop(&lexer); - scc_sstream_drop(&mem_stream); - return ret; +void init_func(void) { + scc_ast_type_builtin_init(&int_type, SCC_AST_BUILTIN_TYPE_INT, + scc_pos_create()); + scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, + scc_pos_create()); + scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, + scc_pos_create()); + scc_ast_type_pointer_init(&pointer_int_type, &int_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_char_type, &char_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_void_type, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_pointer_int_type, &pointer_int_type, + scc_pos_create()); + scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST, + scc_pos_create()); } -typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); - -#define BUFFER_SIZE (4096) -char expect_buffer[BUFFER_SIZE]; -char output_buffer[BUFFER_SIZE]; - -static void dump2buffer(void *_buffer, const char *fmt, ...) { - char *buffer = _buffer; - va_list args; - va_start(args, fmt); - int res = scc_vsnprintf(buffer + strlen(buffer), - BUFFER_SIZE - strlen(buffer) - 1, fmt, args); - Assert(res > 0); - va_end(args); -} - -static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, - 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); - scc_ast_dump_node(&ctx, expect_node_ptr); - scc_tree_dump_ctx_drop(&ctx); - output_buffer[0] = '\n', output_buffer[1] = '\0'; - scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); - scc_ast_dump_node(&ctx, output_node_ptr); - 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, \ - false); \ - TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ - TEST_MSG("Expected: %s", expect_buffer); \ - TEST_MSG("Produced: %s", output_buffer); \ - } while (0); - static void test_parser_unit(void) { // 1. 变量声明 int a; { scc_ast_decl_t int_decl; - scc_ast_decl_val_init( - &int_decl, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null); + scc_ast_decl_val_init(&int_decl, &int_type, "a", null, + scc_pos_create()); SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration); } @@ -110,18 +43,19 @@ static void test_parser_unit(void) { 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_param_init(&void_decl, &void_type, null, scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); // 构造复合语句块(空) scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, null); + scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); // 构造函数声明 scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); SCC_CHECK_AST(&func_decl.base, "int main(void) {}", scc_parse_declaration); @@ -132,17 +66,18 @@ static void test_parser_unit(void) { 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_param_init(&void_decl, &void_type, null, scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, null); + scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); // 构造翻译单元 scc_ast_decl_vec_t tu_decls; @@ -150,7 +85,7 @@ static void test_parser_unit(void) { scc_vec_push(tu_decls, &func_decl); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls); + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); SCC_CHECK_AST(&tu.base, "int main(void) {}", scc_parse_translation_unit); @@ -160,10 +95,11 @@ static void test_parser_unit(void) { { // 返回语句中的整数常量 scc_ast_expr_t ret_val; - scc_ast_expr_literal_int_init(&ret_val, "65536", false); + scc_ast_expr_literal_int_init(&ret_val, "65536", false, + scc_pos_create()); scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &ret_val); + scc_ast_stmt_return_init(&ret_stmt, &ret_val, scc_pos_create()); // 复合语句包含该返回语句 scc_ast_block_item_vec_t items; @@ -171,27 +107,29 @@ static void test_parser_unit(void) { scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items); // items 被移动 + scc_ast_stmt_compound_init(&compound, &items, + scc_pos_create()); // items 被移动 // 函数类型 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_param_init(&void_decl, &void_type, null, scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); scc_ast_decl_vec_t tu_decls; scc_vec_init(tu_decls); scc_vec_push(tu_decls, &func_decl); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls); + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); SCC_CHECK_AST(&tu.base, "int main(void) { return 65536; }", scc_parse_translation_unit); @@ -201,56 +139,63 @@ static void test_parser_unit(void) { { // 变量声明 int a; scc_ast_decl_t a_decl; - scc_ast_decl_val_init(&a_decl, &scc_ast_builtin_type_int, "a", null); + scc_ast_decl_val_init(&a_decl, &int_type, "a", null, scc_pos_create()); // 变量声明 int b; scc_ast_decl_t b_decl; - scc_ast_decl_val_init(&b_decl, &scc_ast_builtin_type_int, "b", null); + scc_ast_decl_val_init(&b_decl, &int_type, "b", null, scc_pos_create()); // 表达式 1 + 2 * 3 scc_ast_expr_t lit1, lit2, lit3, mul, add; - scc_ast_expr_literal_int_init(&lit1, "1", false); - scc_ast_expr_literal_int_init(&lit2, "2", false); - scc_ast_expr_literal_int_init(&lit3, "3", false); - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &mul); + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit3, "3", false, scc_pos_create()); + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3, + scc_pos_create()); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &mul, + scc_pos_create()); // 赋值 a = 1 + 2 * 3; scc_ast_expr_t a_ref1, assign1; - scc_ast_expr_identifier_init(&a_ref1, "a"); - scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add); + scc_ast_expr_identifier_init(&a_ref1, "a", scc_pos_create()); + scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add, + scc_pos_create()); scc_ast_stmt_t assign1_stmt; - scc_ast_stmt_expr_init(&assign1_stmt, &assign1); + scc_ast_stmt_expr_init(&assign1_stmt, &assign1, scc_pos_create()); // 赋值 b = 7; scc_ast_expr_t lit7; - scc_ast_expr_literal_int_init(&lit7, "7", false); + scc_ast_expr_literal_int_init(&lit7, "7", false, scc_pos_create()); scc_ast_expr_t b_ref1, assign2; - scc_ast_expr_identifier_init(&b_ref1, "b"); - scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7); + scc_ast_expr_identifier_init(&b_ref1, "b", scc_pos_create()); + scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7, + scc_pos_create()); scc_ast_stmt_t assign2_stmt; - scc_ast_stmt_expr_init(&assign2_stmt, &assign2); + scc_ast_stmt_expr_init(&assign2_stmt, &assign2, scc_pos_create()); // 表达式 a - b + 1 scc_ast_expr_t a_ref2, b_ref2, sub, add2, lit1_2; - scc_ast_expr_identifier_init(&a_ref2, "a"); - scc_ast_expr_identifier_init(&b_ref2, "b"); - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2); - scc_ast_expr_literal_int_init(&lit1_2, "1", false); - scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2); + scc_ast_expr_identifier_init(&a_ref2, "a", scc_pos_create()); + scc_ast_expr_identifier_init(&b_ref2, "b", scc_pos_create()); + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2, + scc_pos_create()); + scc_ast_expr_literal_int_init(&lit1_2, "1", false, scc_pos_create()); + scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2, + scc_pos_create()); // 赋值 a = a - b + 1; scc_ast_expr_t a_ref3, assign3; - scc_ast_expr_identifier_init(&a_ref3, "a"); - scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2); + scc_ast_expr_identifier_init(&a_ref3, "a", scc_pos_create()); + scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2, + scc_pos_create()); scc_ast_stmt_t assign3_stmt; - scc_ast_stmt_expr_init(&assign3_stmt, &assign3); + scc_ast_stmt_expr_init(&assign3_stmt, &assign3, scc_pos_create()); // return a; scc_ast_expr_t a_ref4; - scc_ast_expr_identifier_init(&a_ref4, "a"); + scc_ast_expr_identifier_init(&a_ref4, "a", scc_pos_create()); scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &a_ref4); + scc_ast_stmt_return_init(&ret_stmt, &a_ref4, scc_pos_create()); // 复合语句块,按顺序放入 scc_ast_block_item_vec_t items; @@ -263,22 +208,23 @@ static void test_parser_unit(void) { scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items); + scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); // 函数类型 scc_ast_type_t func_type; - scc_ast_type_function_init( - &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); + scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, + null, scc_pos_create()); scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); scc_ast_decl_vec_t tu_decls; scc_vec_init(tu_decls); scc_vec_push(tu_decls, &func_decl); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls); + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); const char *input = "int main() {\n" " int a;\n" @@ -295,33 +241,35 @@ static void test_parser_unit(void) { { // 整数字面量 10 scc_ast_expr_t lit10; - scc_ast_expr_literal_int_init(&lit10, "10", false); + scc_ast_expr_literal_int_init(&lit10, "10", false, scc_pos_create()); // 变量声明 int x = 10; scc_ast_decl_t x_decl; - scc_ast_decl_val_init( - &x_decl, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", &lit10); + scc_ast_decl_val_init(&x_decl, (scc_ast_type_t *)&int_type, "x", &lit10, + scc_pos_create()); // 表达式 x + 1 scc_ast_expr_t x_ref1, lit1, add; - scc_ast_expr_identifier_init(&x_ref1, "x"); - scc_ast_expr_literal_int_init(&lit1, "1", false); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &x_ref1, &lit1); + scc_ast_expr_identifier_init(&x_ref1, "x", scc_pos_create()); + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &x_ref1, &lit1, + scc_pos_create()); // 赋值 x = x + 1 scc_ast_expr_t x_ref2, assign; - scc_ast_expr_identifier_init(&x_ref2, "x"); - scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &x_ref2, &add); + scc_ast_expr_identifier_init(&x_ref2, "x", scc_pos_create()); + scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &x_ref2, &add, + scc_pos_create()); // 表达式语句 scc_ast_stmt_t assign_stmt; - scc_ast_stmt_expr_init(&assign_stmt, &assign); + scc_ast_stmt_expr_init(&assign_stmt, &assign, scc_pos_create()); // return x scc_ast_expr_t x_ref3; - scc_ast_expr_identifier_init(&x_ref3, "x"); + scc_ast_expr_identifier_init(&x_ref3, "x", scc_pos_create()); scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &x_ref3); + scc_ast_stmt_return_init(&ret_stmt, &x_ref3, scc_pos_create()); // 复合语句块 scc_ast_block_item_vec_t items; @@ -331,17 +279,18 @@ static void test_parser_unit(void) { scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items); + scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); // 函数类型(返回 int,无参数) scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); // null 表示无参数 + scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, + null, + scc_pos_create()); // null 表示无参数 // 函数声明 int main() { ... } scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); // 翻译单元 scc_ast_decl_vec_t tu_decls; @@ -349,7 +298,7 @@ static void test_parser_unit(void) { scc_vec_push(tu_decls, &func_decl); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls); + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); // 输入源代码 const char *input = "int main() {\n" @@ -365,95 +314,105 @@ static void test_parser_unit(void) { { scc_ast_decl_vec_t params; scc_ast_decl_t param0; - scc_ast_decl_param_init( - ¶m0, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a"); + scc_ast_decl_param_init(¶m0, (scc_ast_type_t *)&int_type, "a", + scc_pos_create()); scc_ast_decl_t param1; - scc_ast_decl_param_init( - ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, "b"); + scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b", + scc_pos_create()); scc_ast_decl_t param2; - scc_ast_decl_param_init( - ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_va_list, null); + scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type, null, + scc_pos_create()); scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2}; scc_vec_unsafe_from_static_array(params, params_array); scc_ast_type_t decl_func_type; - scc_ast_type_function_init(&decl_func_type, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); + scc_ast_type_function_init(&decl_func_type, (scc_ast_type_t *)&int_type, + ¶ms, scc_pos_create()); scc_ast_decl_t decl_func; - scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null); + scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null, + scc_pos_create()); SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);", scc_parse_declaration); } { scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "int32_t", - &scc_ast_builtin_type_int); + scc_ast_decl_typedef_init(&typedef_decl, "int32_t", &int_type, + scc_pos_create()); scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl); + scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl, + scc_pos_create()); scc_ast_decl_t i32a_decl; - scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null); + scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null, + scc_pos_create()); 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_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); 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_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); scc_ast_decl_t void_ptr_decl; - scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr); + scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr, + scc_pos_create()); scc_ast_type_t void_ptr_type; - scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl); + scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl, + scc_pos_create()); scc_ast_decl_t void_ptr_a_decl; - scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null); + scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null, + scc_pos_create()); scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base}; scc_vec_unsafe_from_static_array(items, array2); - scc_ast_stmt_compound_init(&stmt, &items); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); 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_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, + "typedef void * void_ptr; ", scc_parse_declaration); } { // struct { int x; } (匿名结构体定义) scc_ast_decl_t field; - scc_ast_decl_val_init( - &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); + scc_ast_decl_val_init(&field, (scc_ast_type_t *)&int_type, "x", null, + scc_pos_create()); scc_ast_decl_vec_t fields; scc_vec_init(fields); scc_vec_push(fields, &field); scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields); - SCC_CHECK_AST(&struct_def.base, "struct { int x; };", + scc_ast_decl_struct_init(&struct_def, null, &fields, scc_pos_create()); + 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_struct_init(&struct_type, null, &struct_def, + scc_pos_create()); scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def); + scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def, + scc_pos_create()); scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type); + scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type, + scc_pos_create()); 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_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null, + scc_pos_create()); 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_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); SCC_CHECK_AST_WITH_SEMA( &stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}", scc_parse_statement); @@ -461,17 +420,18 @@ static void test_parser_unit(void) { { scc_ast_decl_t type_decl; - scc_ast_decl_typedef_init(&type_decl, "size_t", - &scc_ast_builtin_type_long_long); + scc_ast_decl_typedef_init(&type_decl, "size_t", &int_type, + scc_pos_create()); scc_ast_type_t type_type; - scc_ast_type_typedef_init(&type_type, "size_t", &type_decl); + scc_ast_type_typedef_init(&type_type, "size_t", &type_decl, + scc_pos_create()); scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, &type_type, "a"); + scc_ast_decl_param_init(¶m1, &type_type, "a", scc_pos_create()); scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &scc_ast_builtin_type_int, "b"); + scc_ast_decl_param_init(¶m2, &int_type, "b", scc_pos_create()); scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m3, &scc_ast_builtin_type_va_list, null); + scc_ast_decl_param_init(¶m3, &va_list_type, null, scc_pos_create()); scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_params; scc_vec_unsafe_from_static_array(func_params, params_array); @@ -479,29 +439,32 @@ static void test_parser_unit(void) { 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_type_pointer_init(&return_type, &void_type, scc_pos_create()); + scc_ast_type_function_init(&func_type, &return_type, &func_params, + scc_pos_create()); scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "func", null); + scc_ast_decl_func_init(&func_decl, &func_type, "func", null, + scc_pos_create()); 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_static_array(decls, decls_array); - scc_ast_translation_unit_init(&tu, &decls); + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); SCC_CHECK_AST_WITH_SEMA(&tu.base, - "typedef long long size_t;" + "typedef int 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_type_pointer_init(&type_func_ptr_type, &func_type, + scc_pos_create()); scc_ast_decl_t type_func_ptr_decl; scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t", - &type_func_ptr_type); + &type_func_ptr_type, scc_pos_create()); scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl}; scc_vec_unsafe_from_static_array(decls, decls_array2); - scc_ast_translation_unit_init(&tu, &decls); + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); SCC_CHECK_AST_WITH_SEMA( &tu.base, "typedef long long size_t;" @@ -513,24 +476,27 @@ static void test_parser_unit(void) { // 1. 构造参数类型:volatile const char *restrict,并附加 register // 存储类 scc_ast_type_t char_type; - _scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR); + scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, + scc_pos_create()); char_type.quals.is_const = true; // const char_type.quals.is_volatile = true; // volatile scc_ast_type_t ptr_to_char; - scc_ast_type_pointer_init(&ptr_to_char, &char_type); - ptr_to_char.quals.is_restrict = true; // restrict 限定指针 - ptr_to_char.quals.is_register = true; // register 存储类(作用于参数) + scc_ast_type_pointer_init(&ptr_to_char, &char_type, scc_pos_create()); + ptr_to_char.quals.is_restrict = true; // restrict限定指针 + ptr_to_char.quals.is_register = true; // register存储类(作用于参数) // 2. 参数声明 scc_ast_decl_t param_decl; - scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt"); + scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt", + scc_pos_create()); // 3. 返回类型:void * scc_ast_type_t void_type; - _scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID); + scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, + scc_pos_create()); scc_ast_type_t ptr_to_void; - scc_ast_type_pointer_init(&ptr_to_void, &void_type); + scc_ast_type_pointer_init(&ptr_to_void, &void_type, scc_pos_create()); // 4. 参数列表 scc_ast_decl_vec_t params; @@ -539,13 +505,15 @@ static void test_parser_unit(void) { // 5. 函数类型(包含 static 和 inline) scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms); + scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms, + scc_pos_create()); func_type.quals.is_static = true; func_type.quals.is_inline = true; // 6. 函数声明 scc_ast_decl_t decl; - scc_ast_decl_func_init(&decl, &func_type, "call", null); + scc_ast_decl_func_init(&decl, &func_type, "call", null, + scc_pos_create()); // 7. 与解析结果比较 SCC_CHECK_AST_WITH_SEMA(&decl.base, @@ -556,25 +524,25 @@ static void test_parser_unit(void) { { scc_ast_expr_t lvalue; - scc_ast_expr_lvalue_init(&lvalue, &scc_ast_builtin_type_void); + scc_ast_expr_lvalue_init(&lvalue, &void_type, scc_pos_create()); scc_ast_expr_t lhs1; - scc_ast_expr_member_init(&lhs1, &lvalue, "data"); + scc_ast_expr_member_init(&lhs1, &lvalue, "data", scc_pos_create()); scc_ast_expr_t lhs2; - scc_ast_expr_member_init(&lhs2, &lvalue, "size"); + scc_ast_expr_member_init(&lhs2, &lvalue, "size", scc_pos_create()); scc_ast_expr_t lhs3; - scc_ast_expr_member_init(&lhs3, &lvalue, "cap"); + scc_ast_expr_member_init(&lhs3, &lvalue, "cap", scc_pos_create()); scc_ast_expr_t rl0; - scc_ast_expr_literal_int_init(&rl0, "0", false); + scc_ast_expr_literal_int_init(&rl0, "0", false, scc_pos_create()); scc_ast_type_t void_ptr; - scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); + scc_ast_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); scc_ast_expr_t rhs1; - scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0); + scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0, scc_pos_create()); scc_ast_expr_t rhs2; - scc_ast_expr_literal_int_init(&rhs2, "0", false); + scc_ast_expr_literal_int_init(&rhs2, "0", false, scc_pos_create()); scc_ast_expr_t rhs3; - scc_ast_expr_literal_int_init(&rhs3, "0", false); + scc_ast_expr_literal_int_init(&rhs3, "0", false, scc_pos_create()); scc_ast_expr_vec_t lhs_exprs; scc_ast_expr_t *lhs_array[] = {&lhs1, &lhs2, &lhs3}; @@ -585,7 +553,8 @@ static void test_parser_unit(void) { scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array); scc_ast_expr_t expr; - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, + scc_pos_create()); // FIXME use real records type SCC_CHECK_AST(&expr.base, @@ -593,25 +562,27 @@ static void test_parser_unit(void) { scc_parse_expression); scc_ast_stmt_t stmt; - scc_ast_stmt_return_init(&stmt, &expr); - SCC_CHECK_AST(&stmt.base, - "return (void){.data = (void *)0, .size = 0, .cap = 0};", - scc_parse_statement); + scc_ast_stmt_return_init(&stmt, &expr, scc_pos_create()); + SCC_CHECK_AST( + &stmt.base, + "return (void){.data = (void *)0, .size = 0, .cap = 0 }; ", + scc_parse_statement); scc_ast_expr_t lhs4; scc_ast_expr_t lhs5; - scc_ast_expr_member_init(&lhs4, &lvalue, "a"); - scc_ast_expr_member_init(&lhs5, &lhs4, "b"); + scc_ast_expr_member_init(&lhs4, &lvalue, "a", scc_pos_create()); + scc_ast_expr_member_init(&lhs5, &lhs4, "b", scc_pos_create()); scc_ast_expr_t lhs6; scc_ast_expr_t lhs7; - scc_ast_expr_member_init(&lhs6, &lvalue, "c"); - scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0); + scc_ast_expr_member_init(&lhs6, &lvalue, "c", scc_pos_create()); + scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0, scc_pos_create()); scc_ast_expr_t *lhs_array_hard[] = {&lhs5, &lhs7}; scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array_hard); scc_ast_expr_t *rhs_array_hard[] = {&rhs2, &rhs3}; scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array_hard); - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, + scc_pos_create()); SCC_CHECK_AST(&expr.base, "(void){.a.b = 0, .c[0] = 0}", scc_parse_expression); } @@ -622,7 +593,8 @@ static void test_parser_unit(void) { scc_ast_decl_t struct_decl; scc_ast_decl_vec_t empty_members; scc_vec_init(empty_members); - scc_ast_decl_struct_init(&struct_decl, "S", &empty_members); + scc_ast_decl_struct_init(&struct_decl, "S", &empty_members, + scc_pos_create()); SCC_CHECK_AST(&struct_decl.base, "struct S;", scc_parse_declaration); } @@ -632,7 +604,8 @@ static void test_parser_unit(void) { scc_ast_decl_t union_decl; scc_ast_decl_vec_t empty_members; scc_vec_init(empty_members); - scc_ast_decl_union_init(&union_decl, "U", &empty_members); + scc_ast_decl_union_init(&union_decl, "U", &empty_members, + scc_pos_create()); SCC_CHECK_AST(&union_decl.base, "union U;", scc_parse_declaration); } @@ -641,21 +614,19 @@ static void test_parser_unit(void) { scc_ast_decl_t enum_decl; scc_ast_expr_vec_t empty_enumerators; scc_vec_init(empty_enumerators); - scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators); + scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators, + scc_pos_create()); SCC_CHECK_AST(&enum_decl.base, "enum E;", scc_parse_declaration); } } { scc_ast_stmt_t continue_stmt; - scc_ast_stmt_continue_init(&continue_stmt); + scc_ast_stmt_continue_init(&continue_stmt, scc_pos_create()); scc_ast_stmt_t stmt; - scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt); + scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt, + scc_pos_create()); SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement); - - scc_ast_expr_t str; - scc_ast_expr_literal_string_init(&str, "\"ab\"", false); - SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression); } { @@ -663,27 +634,27 @@ static void test_parser_unit(void) { { // 构造类型 int* scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); + scc_ast_type_pointer_init(&ptr_to_int, (scc_ast_type_t *)&int_type, + scc_pos_create()); // 标识符 b scc_ast_expr_t b_expr; - scc_ast_expr_identifier_init(&b_expr, "b"); + scc_ast_expr_identifier_init(&b_expr, "b", scc_pos_create()); // 类型转换 (int*)b scc_ast_expr_t cast_expr; - scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr); + scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr, + scc_pos_create()); // 解引用 *(int*)b scc_ast_expr_t deref_expr; scc_ast_expr_unary_init(&deref_expr, SCC_AST_OP_INDIRECTION, - &cast_expr); + &cast_expr, scc_pos_create()); // 声明 int a = *(int*)b; scc_ast_decl_t decl; - scc_ast_decl_val_init(&decl, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", &deref_expr); + scc_ast_decl_val_init(&decl, (scc_ast_type_t *)&int_type, "a", + &deref_expr, scc_pos_create()); SCC_CHECK_AST(&decl.base, "int a = *(int*)b;", scc_parse_declaration); @@ -692,12 +663,10 @@ static void test_parser_unit(void) { // 测试 int a, b; { scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", null); - scc_ast_decl_val_init(&decl_b, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "b", null); + scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", + null, scc_pos_create()); + scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", + null, scc_pos_create()); scc_ast_decl_vec_t decl_vec; scc_vec_init(decl_vec); @@ -705,7 +674,8 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &decl_b); 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_pos_create()); // 假设存在该函数 SCC_CHECK_AST(&decl_list.base, "int a, b;", scc_parse_declaration); } @@ -713,16 +683,14 @@ static void test_parser_unit(void) { // 测试 int a = 1, b = 2; { scc_ast_expr_t lit1, lit2; - scc_ast_expr_literal_int_init(&lit1, "1", false); - scc_ast_expr_literal_int_init(&lit2, "2", false); + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", &lit1); - scc_ast_decl_val_init(&decl_b, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "b", &lit2); + scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", + &lit1, scc_pos_create()); + scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", + &lit2, scc_pos_create()); scc_ast_decl_vec_t decl_vec; scc_vec_init(decl_vec); @@ -730,7 +698,8 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &decl_b); 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_pos_create()); // 假设存在该函数 SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;", scc_parse_declaration); @@ -739,17 +708,22 @@ static void test_parser_unit(void) { { // 构造 struct list_head 类型(不完整) scc_ast_type_t struct_list_head; - scc_ast_type_struct_init(&struct_list_head, "list_head", null); + scc_ast_type_struct_init(&struct_list_head, "list_head", null, + scc_pos_create()); // 构造两个指针类型(分别用于 next 和 prev,指向同一结构体) scc_ast_type_t ptr_to_struct1, ptr_to_struct2; - scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head); - scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head); + scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head, + scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head, + scc_pos_create()); // 构造变量声明 next 和 prev scc_ast_decl_t next_decl, prev_decl; - scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null); - scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null); + scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null, + scc_pos_create()); + scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null, + scc_pos_create()); // 构造声明列表 scc_ast_decl_vec_t decl_vec; @@ -757,7 +731,7 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &next_decl); scc_vec_push(decl_vec, &prev_decl); 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_pos_create()); SCC_CHECK_AST(&decl_list.base, "struct list_head *next, *prev;", scc_parse_declaration); @@ -767,9 +741,8 @@ static void test_parser_unit(void) { { // 构造字段 int a; scc_ast_decl_t field_a; - scc_ast_decl_val_init(&field_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", null); + scc_ast_decl_val_init(&field_a, (scc_ast_type_t *)&int_type, "a", + null, scc_pos_create()); scc_ast_decl_vec_t fields; scc_vec_init(fields); @@ -777,26 +750,28 @@ static void test_parser_unit(void) { // 构造匿名结构体定义声明 scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, - &fields); // fields 被移动 + scc_ast_decl_struct_init(&struct_def, null, &fields, + scc_pos_create()); // fields 被移动 // 构造匿名结构体类型 scc_ast_type_t anon_struct_type; - scc_ast_type_struct_init(&anon_struct_type, null, &struct_def); + scc_ast_type_struct_init(&anon_struct_type, null, &struct_def, + scc_pos_create()); // 构造指针类型指向该匿名结构体 scc_ast_type_t ptr_to_anon; - scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type); + scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type, + scc_pos_create()); // 构造 typedef 声明 struct_t scc_ast_decl_t typedef_struct_t; scc_ast_decl_typedef_init(&typedef_struct_t, "struct_t", - &anon_struct_type); + &anon_struct_type, scc_pos_create()); // 构造 typedef 声明 struct_ptr_t scc_ast_decl_t typedef_struct_ptr_t; scc_ast_decl_typedef_init(&typedef_struct_ptr_t, "struct_ptr_t", - &ptr_to_anon); + &ptr_to_anon, scc_pos_create()); // 构造声明列表 scc_ast_decl_vec_t typedef_vec; @@ -804,7 +779,7 @@ static void test_parser_unit(void) { scc_vec_push(typedef_vec, &typedef_struct_t); scc_vec_push(typedef_vec, &typedef_struct_ptr_t); scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &typedef_vec); + scc_ast_decl_list_init(&decl_list, &typedef_vec, scc_pos_create()); SCC_CHECK_AST(&decl_list.base, "typedef struct { int a; } struct_t, *struct_ptr_t;", @@ -820,53 +795,57 @@ static void test_parser_unit(void) { // 步骤: // 1) 数组类型:int [5] scc_ast_expr_t size_5; - scc_ast_expr_literal_int_init(&size_5, "5", false); + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); 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); + scc_ast_type_array_init(&array_of_5_int, (scc_ast_type_t *)&int_type, + &size_5, scc_pos_create()); // 2) 函数类型:返回指向数组的指针,无参数 scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int, + scc_pos_create()); 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_param_init(&void_decl, &void_type, null, scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &ptr_to_array, - &func_params); // 无参数 + scc_ast_type_function_init(&func_type, &ptr_to_array, &func_params, + scc_pos_create()); // 无参数 // 3) 指向该函数的指针 scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); scc_ast_decl_t ptr_to_func_decl; - scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null); + scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null, + scc_pos_create()); 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_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func, + scc_pos_create()); scc_ast_type_t typedef_func_type; scc_ast_type_typedef_init(&typedef_func_type, "func_t", - &typedef_func_decl); + &typedef_func_decl, scc_pos_create()); 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_param_init(¶m1, &ptr_to_func, "bar", scc_pos_create()); scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &typedef_func_type, "a"); + scc_ast_decl_param_init(¶m2, &typedef_func_type, "a", + scc_pos_create()); scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m1, &scc_ast_builtin_type_va_list, null); + scc_ast_decl_param_init(¶m1, &va_list_type, null, scc_pos_create()); scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_hard_params; scc_vec_unsafe_from_static_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); + &func_hard_params, scc_pos_create()); + scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null, + scc_pos_create()); scc_ast_decl_vec_t decls; scc_ast_decl_t *decls_array[] = { @@ -875,7 +854,7 @@ static void test_parser_unit(void) { }; scc_vec_unsafe_from_static_array(decls, decls_array); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &decls); + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); // SCC_CHECK_AST_WITH_SEMA( // &tu.base, // "typedef int (*(*func_t)(void))[5];" @@ -884,901 +863,7 @@ static void test_parser_unit(void) { } } -static void test_parser_expression(void) { - // 1. 基本表达式 - { - scc_ast_expr_t ident; - scc_ast_expr_identifier_init(&ident, "x"); - SCC_CHECK_AST(&ident.base, "x", scc_parse_expression); - - scc_ast_expr_t int_lit; - scc_ast_expr_literal_int_init(&int_lit, "42", false); - SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression); - - scc_ast_expr_t str_lit; - scc_ast_expr_literal_string_init(&str_lit, "\"hello\"", false); - SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression); - - // 括号表达式(解析器应直接返回内部表达式) - scc_ast_expr_t paren_ident; - scc_ast_expr_identifier_init(&paren_ident, "y"); - SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression); - } - - // 2. 后缀表达式 - { - // 数组下标 a[10] - scc_ast_expr_t a, index, subscript; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_literal_int_init(&index, "10", false); - scc_ast_expr_array_subscript_init(&subscript, &a, &index); - SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); - - // 函数调用 f() - scc_ast_expr_t f; - scc_ast_expr_identifier_init(&f, "f"); - scc_ast_expr_vec_t args; - scc_vec_init(args); - scc_ast_expr_t call; - scc_ast_expr_t callee1; - scc_ast_expr_identifier_init(&callee1, "f"); - scc_ast_expr_call_init(&call, &callee1, - &args); // 使用函数名,target 在语义分析时填充 - SCC_CHECK_AST(&call.base, "f()", scc_parse_expression); - - // 函数调用带参数 f(1, x) - scc_ast_expr_t arg1, arg2; - scc_ast_expr_literal_int_init(&arg1, "1", false); - scc_ast_expr_identifier_init(&arg2, "x"); - scc_ast_expr_vec_t args2; - scc_vec_init(args2); - scc_vec_push(args2, &arg1); - scc_vec_push(args2, &arg2); - scc_ast_expr_t callee2; - scc_ast_expr_identifier_init(&callee2, "f"); - scc_ast_expr_t call2; - scc_ast_expr_call_init(&call2, &callee2, &args2); - SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); - - // 成员访问 . - scc_ast_expr_t s, dot; - scc_ast_expr_identifier_init(&s, "s"); - scc_ast_expr_member_init(&dot, &s, "field"); - SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression); - - // 指针成员访问 -> - scc_ast_expr_t p, arrow; - scc_ast_expr_identifier_init(&p, "p"); - scc_ast_expr_ptr_member_init(&arrow, &p, "field"); - SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression); - - // 后缀 ++/-- - scc_ast_expr_t x, post_inc, post_dec; - scc_ast_expr_identifier_init(&x, "x"); - scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &x); - scc_ast_expr_unary_init(&post_dec, SCC_AST_OP_POSTFIX_DECREMENT, &x); - SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression); - SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression); - } - - // 3. 一元表达式 - { - scc_ast_expr_t x; - scc_ast_expr_identifier_init(&x, "x"); - - scc_ast_expr_t pre_inc; - scc_ast_expr_unary_init(&pre_inc, SCC_AST_OP_PREFIX_INCREMENT, &x); - SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression); - - scc_ast_expr_t pre_dec; - scc_ast_expr_unary_init(&pre_dec, SCC_AST_OP_PREFIX_DECREMENT, &x); - SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression); - - scc_ast_expr_t addr; - scc_ast_expr_unary_init(&addr, SCC_AST_OP_ADDRESS_OF, &x); - SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression); - - scc_ast_expr_t deref; - scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &x); - SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression); - - scc_ast_expr_t plus; - scc_ast_expr_unary_init(&plus, SCC_AST_OP_UNARY_PLUS, &x); - SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression); - - scc_ast_expr_t minus; - scc_ast_expr_unary_init(&minus, SCC_AST_OP_UNARY_MINUS, &x); - SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression); - - scc_ast_expr_t bit_not; - scc_ast_expr_unary_init(&bit_not, SCC_AST_OP_BITWISE_NOT, &x); - SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression); - - scc_ast_expr_t log_not; - scc_ast_expr_unary_init(&log_not, SCC_AST_OP_LOGICAL_NOT, &x); - SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression); - - // sizeof 表达式 - scc_ast_expr_t sizeof_x_expr; - scc_ast_expr_sizeof_init(&sizeof_x_expr, null, &x); - SCC_CHECK_AST(&sizeof_x_expr.base, "sizeof(x)", scc_parse_expression); - - scc_ast_expr_t sizeof_int_expr; - scc_ast_expr_sizeof_init(&sizeof_int_expr, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); - SCC_CHECK_AST(&sizeof_int_expr.base, "sizeof(int)", - scc_parse_expression); - } - - // 4. 类型转换(示例: (int)x ) - { - 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. 二元运算符优先级 - { - scc_ast_expr_t a, b, c, d; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_identifier_init(&d, "d"); - - // a * b + c - scc_ast_expr_t mul, add; - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &a, &b); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &mul, &c); - SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression); - - // a - b - c => (a - b) - c - scc_ast_expr_t sub1, sub2; - scc_ast_expr_binary_init(&sub1, SCC_AST_OP_SUB, &a, &b); - scc_ast_expr_binary_init(&sub2, SCC_AST_OP_SUB, &sub1, &c); - SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression); - - // a << b - scc_ast_expr_t shift; - scc_ast_expr_binary_init(&shift, SCC_AST_OP_LEFT_SHIFT, &a, &b); - SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression); - - // a < b - scc_ast_expr_t lt; - scc_ast_expr_binary_init(<, SCC_AST_OP_LESS, &a, &b); - SCC_CHECK_AST(<.base, "a < b", scc_parse_expression); - - // a == b - scc_ast_expr_t eq; - scc_ast_expr_binary_init(&eq, SCC_AST_OP_EQUAL, &a, &b); - SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression); - - // a & b ^ c | d - scc_ast_expr_t bitand, bitxor, bitor; - scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b); - scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c); - scc_ast_expr_binary_init(&bitor, SCC_AST_OP_BITWISE_OR, &bitxor, &d); - SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression); - - // a && b || c - scc_ast_expr_t logand, logor; - scc_ast_expr_binary_init(&logand, SCC_AST_OP_LOGICAL_AND, &a, &b); - scc_ast_expr_binary_init(&logor, SCC_AST_OP_LOGICAL_OR, &logand, &c); - SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression); - } - - // 6. 三元运算符 - { - scc_ast_expr_t a, b, c; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - - // a ? b : c - scc_ast_expr_t cond1; - scc_ast_expr_cond_init(&cond1, &a, &b, &c); - SCC_CHECK_AST(&cond1.base, "a ? b : c", scc_parse_expression); - - // a ? b : c ? d : e => a ? b : (c ? d : e) - scc_ast_expr_t d, e; - scc_ast_expr_identifier_init(&d, "d"); - scc_ast_expr_identifier_init(&e, "e"); - scc_ast_expr_t inner, outer; - scc_ast_expr_cond_init(&inner, &c, &d, &e); - scc_ast_expr_cond_init(&outer, &a, &b, &inner); - SCC_CHECK_AST(&outer.base, "a ? b : c ? d : e", scc_parse_expression); - } - - // 7. 赋值运算符 - { - scc_ast_expr_t a, b, c; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_t lit42; - scc_ast_expr_literal_int_init(&lit42, "42", false); - - // a = b = c - scc_ast_expr_t assign_inner, assign_outer; - scc_ast_expr_binary_init(&assign_inner, SCC_AST_OP_ASSIGN, &b, &c); - scc_ast_expr_binary_init(&assign_outer, SCC_AST_OP_ASSIGN, &a, - &assign_inner); - SCC_CHECK_AST(&assign_outer.base, "a = b = c", scc_parse_expression); - - // a = 42 - scc_ast_expr_t assign1; - scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a, &lit42); - SCC_CHECK_AST(&assign1.base, "a = 42", scc_parse_expression); - - // a = a - b + 42 - scc_ast_expr_t sub, add, assign2; - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a, &b); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &sub, &lit42); - scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &a, &add); - SCC_CHECK_AST(&assign2.base, "a = a - b + 42", scc_parse_expression); - - // a += b - scc_ast_expr_t add_assign; - scc_ast_expr_binary_init(&add_assign, SCC_AST_OP_ASSIGN_ADD, &a, &b); - SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression); - } - - // 8. 逗号运算符 - { - scc_ast_expr_t a, b; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_t comma; - scc_ast_expr_binary_init(&comma, SCC_AST_OP_COMMA, &a, &b); - SCC_CHECK_AST(&comma.base, "a, b", scc_parse_expression); - } - - // 9. 混合优先级 - { - scc_ast_expr_t a, b, c, d; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_identifier_init(&d, "d"); - - // a + b * c - d - scc_ast_expr_t mul, add, sub; - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &a, &mul); - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &add, &d); - SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression); - - // *p++ - scc_ast_expr_t p, post_inc, deref; - scc_ast_expr_identifier_init(&p, "p"); - scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &p); - scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &post_inc); - SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression); - } -} - -static void test_parser_type(void) { - { - // 1. int - { - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int", - scc_parse_type_name); - } - - // 2. int * - { - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); - } - - // 3. int *[3] - { - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_int, &size_3); - SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", scc_parse_type_name); - } - - // 4. int (*)[3] - { - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - - scc_ast_type_t array_of_int; - scc_ast_type_array_init(&array_of_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_3); - - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_int); - SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]", - scc_parse_type_name); - } - - // 5. int (*)[*] - { - scc_ast_type_t array_of_int_var; - scc_ast_type_array_init(&array_of_int_var, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); // null 表示不定长数组 - - scc_ast_type_t ptr_to_array_var; - scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var); - SCC_CHECK_AST(&ptr_to_array_var.base, "int (*)[*]", - scc_parse_type_name); - } - - // 6. int *() - { - // 返回类型 int* - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - - // 函数类型,返回 int*,无参数 - scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &ptr_to_int, null); - SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name); - } - - // 7. int (*)(void) - { - // 函数类型,返回 int,无参数 - scc_ast_type_t func_void; - 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_static_array(func_params, array); - scc_ast_type_function_init( - &func_void, (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params); - - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_void); - SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", - scc_parse_type_name); - } - - // 8. int (*const [])(unsigned int, ...) - { - // --- 构造参数列表 --- - // 第一个参数:unsigned int - scc_ast_decl_t param_uint; - scc_ast_decl_param_init( - ¶m_uint, - (scc_ast_type_t *)&scc_ast_builtin_type_unsigned_int, "u"); - - // 第二个参数:... 用内置 va_list 类型近似表示 - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, - SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_t param_var; - scc_ast_decl_param_init(¶m_var, &va_list_type, "..."); - - scc_ast_decl_vec_t params; - scc_vec_init(params); - scc_vec_push(params, ¶m_uint); - scc_vec_push(params, ¶m_var); - - // --- 函数类型,返回 int --- - scc_ast_type_t func_type; - scc_ast_type_function_init( - &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); // params 被移动 - - // --- 指向函数的指针,带 const 限定 --- - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - ptr_to_func.quals.is_const = true; // 设置 const - - // --- 数组,元素为上述 const 指针,大小未指定 --- - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, null); - - SCC_CHECK_AST(&array_of_ptr.base, - "int (*const [])(unsigned int, ...)", - scc_parse_type_name); - } - } - - // 1. 基本内置类型及组合 - { - // int - SCC_CHECK_AST(&scc_ast_builtin_type_int.base, "int", - scc_parse_type_name); - - // char - SCC_CHECK_AST(&scc_ast_builtin_type_char.base, "char", - scc_parse_type_name); - - // long long - SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long", - scc_parse_type_name); - - // long long - SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long int", - scc_parse_type_name); - - // short - SCC_CHECK_AST(&scc_ast_builtin_type_short.base, "short int", - scc_parse_type_name); - - // unsigned int - SCC_CHECK_AST(&scc_ast_builtin_type_unsigned_int.base, "unsigned int", - scc_parse_type_name); - - // float - SCC_CHECK_AST(&scc_ast_builtin_type_float.base, "float", - scc_parse_type_name); - - // double - SCC_CHECK_AST(&scc_ast_builtin_type_double.base, "double", - scc_parse_type_name); - - // void - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_void, "void", - scc_parse_type_name); - - // bool - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_bool, "bool", - scc_parse_type_name); - - // long double - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_double, - "long double", scc_parse_type_name); - - // _Complex double - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double, - "double complex", scc_parse_type_name); - } - - // 2. 带类型限定符的基本类型 (const, volatile) - { - // const int - scc_ast_type_t const_int = scc_ast_builtin_type_int; - const_int.quals.is_const = true; - SCC_CHECK_AST(&const_int.base, "const int", scc_parse_type_name); - - // volatile unsigned long - scc_ast_type_t volatile_ulong = scc_ast_builtin_type_unsigned_long; - volatile_ulong.quals.is_volatile = true; - SCC_CHECK_AST(&volatile_ulong.base, "volatile unsigned long", - scc_parse_type_name); - - // const volatile char - scc_ast_type_t const_volatile_char = scc_ast_builtin_type_char; - const_volatile_char.quals.is_const = true; - const_volatile_char.quals.is_volatile = true; - SCC_CHECK_AST(&const_volatile_char.base, "const volatile char", - scc_parse_type_name); - } - - // 3. 指针类型 - { - // int * - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init(&ptr_to_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); - - // int ** - scc_ast_type_t ptr_to_ptr_to_int; - scc_ast_type_pointer_init(&ptr_to_ptr_to_int, &ptr_to_int); - SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", scc_parse_type_name); - - // int * const (const pointer to int) - scc_ast_type_t const_ptr_to_int; - scc_ast_type_pointer_init(&const_ptr_to_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - const_ptr_to_int.quals.is_const = true; - SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", - scc_parse_type_name); - - // const int * (pointer to const int) - scc_ast_type_t const_int_type = scc_ast_builtin_type_int; - const_int_type.quals.is_const = true; - scc_ast_type_t ptr_to_const_int; - scc_ast_type_pointer_init(&ptr_to_const_int, &const_int_type); - SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", - scc_parse_type_name); - - // const int * const (const pointer to const int) - scc_ast_type_t const_ptr_to_const_int; - scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int_type); - const_ptr_to_const_int.quals.is_const = true; - SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const", - scc_parse_type_name); - - // volatile int * restrict - scc_ast_type_t volatile_int = scc_ast_builtin_type_int; - volatile_int.quals.is_volatile = true; - scc_ast_type_t restrict_ptr_to_volatile_int; - scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int); - restrict_ptr_to_volatile_int.quals.is_restrict = true; - SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base, - "volatile int * restrict", scc_parse_type_name); - } - - // 4. 数组类型 - { - // 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); - SCC_CHECK_AST(&array_of_5_int.base, "int [5]", scc_parse_type_name); - - // int [] (不完整类型) - scc_ast_type_t array_of_int_unknown; - scc_ast_type_array_init(&array_of_int_unknown, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); - SCC_CHECK_AST(&array_of_int_unknown.base, "int []", - scc_parse_type_name); - - // // int [*] (变长数组原型中的不定长数组) - // FIXME - // scc_ast_type_t array_of_int_var; - // scc_ast_type_array_init(&array_of_int_var, - // (scc_ast_type_t *)&scc_ast_builtin_type_int, - // null); - // // 注意:[*] 与 [] 在AST中目前无法区分,都使用 size=null - // // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对 - // [*] - // // 也生成 size=null 的数组节点。 - // SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type); - - // int [5][3] (二维数组) - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - scc_ast_type_t inner_array; - scc_ast_type_array_init( - &inner_array, (scc_ast_type_t *)&scc_ast_builtin_type_int, &size_3); - scc_ast_type_t outer_array; - scc_ast_type_array_init(&outer_array, &inner_array, &size_5); - SCC_CHECK_AST(&outer_array.base, "int [5][3]", scc_parse_type_name); - - // int (*)[5] (指向数组的指针) 已在前面测试,这里重复以保持完整性 - scc_ast_type_t array_of_5_int2; - scc_ast_type_array_init(&array_of_5_int2, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_5); - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int2); - SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", scc_parse_type_name); - - // int *[5] (指针数组) - scc_ast_type_t ptr_to_int2; - scc_ast_type_pointer_init(&ptr_to_int2, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - scc_ast_type_t array_of_5_ptr; - scc_ast_type_array_init(&array_of_5_ptr, &ptr_to_int2, &size_5); - SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", scc_parse_type_name); - - // const int [5] (数组元素为const int) - scc_ast_type_t const_int2 = scc_ast_builtin_type_int; - const_int2.quals.is_const = true; - scc_ast_type_t const_array; - scc_ast_type_array_init(&const_array, &const_int2, &size_5); - SCC_CHECK_AST(&const_array.base, "const int [5]", scc_parse_type_name); - } - - // 5. 函数类型 - { - // int (void) - scc_ast_type_t func_void; - 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_static_array(func_params, array); - scc_ast_type_function_init(&func_void, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params); - SCC_CHECK_AST(&func_void.base, "int (void)", scc_parse_type_name); - - // // int () (无参数声明,非原型) - // // - // 在C中,空括号表示未指定参数,但AST中可能仍然用空参数列表表示。这里假设与 - // // (void) 相同。 - // SCC_CHECK_AST(&func_void.base, "int ()", scc_parse_type); - - // int (int, float) - scc_ast_decl_t param1, param2; - scc_ast_decl_param_init( - ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_decl_param_init( - ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_float, null); - scc_ast_decl_vec_t params; - scc_vec_init(params); - scc_vec_push(params, ¶m1); - scc_vec_push(params, ¶m2); - - scc_ast_type_t func_with_params; - scc_ast_type_function_init(&func_with_params, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); - SCC_CHECK_AST(&func_with_params.base, "int (int, float)", - scc_parse_type_name); - - // int (int, ...) (可变参数) - scc_ast_decl_t param_int, param_var; - scc_ast_decl_param_init( - ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_param_init(¶m_var, &va_list_type, null); - scc_ast_decl_vec_t params_var; - scc_vec_init(params_var); - scc_vec_push(params_var, ¶m_int); - scc_vec_push(params_var, ¶m_var); - - scc_ast_type_t func_varargs; - scc_ast_type_function_init(&func_varargs, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms_var); - SCC_CHECK_AST(&func_varargs.base, "int (int, ...)", - scc_parse_type_name); - - // int (*)(int) (函数指针) - scc_ast_decl_t param; - scc_ast_decl_param_init( - ¶m, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_decl_vec_t params2; - scc_vec_init(params2); - scc_vec_push(params2, ¶m); - - scc_ast_type_t func_type; - scc_ast_type_function_init( - &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, ¶ms2); - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", scc_parse_type_name); - } - - // 6. 函数指针和复杂声明符 - { - // int (*foo)(void) - // 这里应解析为类型名,但包含标识符?我们的解析函数是scc_parse_type,它应该解析类型名,不应包含标识符。 - // 所以跳过带标识符的,只测试抽象声明符。 - - // 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_static_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_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]", - scc_parse_type_name); - - // int (*(*)[5])(void) (指向数组的指针,数组元素为函数指针) - // 1) 函数类型:返回 int,无参数 - scc_ast_type_t func_type2; - scc_ast_decl_vec_t func_params2; - scc_vec_unsafe_from_static_array(func_params2, array); - scc_ast_type_function_init(&func_type2, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params2); - - // 2) 指针指向该函数 - scc_ast_type_t ptr_to_func2; - scc_ast_type_pointer_init(&ptr_to_func2, &func_type2); - - // 3) 数组,元素为上述指针 - scc_ast_type_t array_of_ptr_to_func; - scc_ast_type_array_init(&array_of_ptr_to_func, &ptr_to_func2, &size_5); - - // 4) 指针指向该数组 - scc_ast_type_t ptr_to_array_of_ptr; - scc_ast_type_pointer_init(&ptr_to_array_of_ptr, &array_of_ptr_to_func); - SCC_CHECK_AST(&ptr_to_array_of_ptr.base, "int (*(*)[5])(void)", - scc_parse_type_name); - } - - // 7. 结构体/联合/枚举类型(标记和定义) - { - // struct S (不完整类型) - scc_ast_type_t struct_tag; - scc_ast_type_struct_init(&struct_tag, "S", - null); // name="S", members=null - SCC_CHECK_AST(&struct_tag.base, "struct S", scc_parse_type_name); - - // struct { int x; } (匿名结构体定义) - scc_ast_decl_t field; - scc_ast_decl_val_init( - &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); - scc_ast_decl_vec_t fields; - scc_vec_init(fields); - scc_vec_push(fields, &field); - - scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields); - scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, null, &struct_def); - SCC_CHECK_AST(&struct_type.base, "struct { int x; }", - scc_parse_type_name); - scc_vec_init(fields); - scc_vec_push(fields, &field); - scc_ast_decl_struct_init(&struct_def, "A", &fields); - scc_ast_type_struct_init(&struct_type, "A", &struct_def); - SCC_CHECK_AST(&struct_type.base, "struct A { int x; }", - scc_parse_type_name); - - // union U (不完整类型) - scc_ast_type_t union_tag; - scc_ast_type_union_init(&union_tag, "U", null); - SCC_CHECK_AST(&union_tag.base, "union U", scc_parse_type_name); - - // union { int a; float b; } (匿名联合定义) - scc_ast_decl_t field_a, field_b; - scc_ast_decl_val_init( - &field_a, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null); - scc_ast_decl_val_init( - &field_b, (scc_ast_type_t *)&scc_ast_builtin_type_float, "b", null); - scc_ast_decl_vec_t fields_union; - scc_vec_init(fields_union); - scc_vec_push(fields_union, &field_a); - scc_vec_push(fields_union, &field_b); - - scc_ast_decl_t union_def; - scc_ast_decl_union_init(&union_def, null, &fields_union); - scc_ast_type_t union_type; - scc_ast_type_union_init(&union_type, null, &union_def); - SCC_CHECK_AST(&union_type.base, "union { int a; float b; }", - scc_parse_type_name); - scc_ast_decl_union_init(&union_def, "Union", &fields_union); - scc_ast_type_union_init(&union_type, "Union", &union_def); - SCC_CHECK_AST(&union_type.base, "union Union { int a; float b; }", - scc_parse_type_name); - - // enum E (不完整类型) - scc_ast_type_t enum_tag; - scc_ast_type_enum_init(&enum_tag, "E", null); - SCC_CHECK_AST(&enum_tag.base, "enum E", scc_parse_type_name); - - // enum { RED, GREEN, BLUE } (匿名枚举定义) - scc_ast_expr_t red, green, blue; - scc_ast_expr_identifier_init(&red, "RED"); - scc_ast_expr_identifier_init(&green, "GREEN"); - scc_ast_expr_identifier_init(&blue, "BLUE"); - scc_ast_expr_vec_t enumerators; - scc_ast_expr_t *array[] = {&red, &green, &blue}; - scc_vec_unsafe_from_static_array(enumerators, array); - - scc_ast_decl_t enum_def; - scc_ast_decl_enum_init(&enum_def, null, &enumerators); - scc_ast_type_t enum_type; - scc_ast_type_enum_init(&enum_type, null, &enum_def); - SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", - scc_parse_type_name); - - scc_vec_unsafe_from_static_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_parse_type_name); - } - - // 8. typedef 类型 - { - // 假设存在 typedef int myint; 但类型解析时,遇到 myint - // 应得到对应的类型节点。 为了测试,我们直接构造一个 typedef 类型节点。 - // scc_ast_type_t myint_type; - // scc_ast_type_typedef_init(&myint_type, "myint", - // (scc_ast_type_t - // *)&scc_ast_builtin_type_int); - // SCC_CHECK_AST(&myint_type.base, "myint", scc_parse_type); - - // // myint * (指针指向 typedef 类型) - // scc_ast_type_t ptr_to_myint; - // scc_ast_type_pointer_init(&ptr_to_myint, &myint_type); - // SCC_CHECK_AST(&ptr_to_myint.base, "myint *", scc_parse_type); - } - - // 9. 混合复杂类型 - { - // const int * volatile (*)[10] - // 步骤: - // 1) const int - scc_ast_type_t const_int = scc_ast_builtin_type_int; - const_int.quals.is_const = true; - - // 2) 指针指向 const int (普通指针) - scc_ast_type_t ptr_to_const_int; - scc_ast_type_pointer_init(&ptr_to_const_int, &const_int); - // 该指针本身是 volatile 限定?语法上 "const int * volatile" 表示指针是 - // volatile 的,指向 const int。 - ptr_to_const_int.quals.is_volatile = true; - - // 3) 数组,元素为上述指针,大小为10 - scc_ast_expr_t size_10; - scc_ast_expr_literal_int_init(&size_10, "10", false); - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_const_int, &size_10); - - // 4) 指针指向该数组 - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr); - SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]", - scc_parse_type_name); - - // float (*(*)(int, ...))() - // 1) float 类型作为内部函数返回类型 - // 2) 构建返回 float 的函数类型,无参数(或者参数为空) - scc_ast_type_t func_ret_float; - scc_ast_type_function_init( - &func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float, - null); - - // 3) 指针指向该函数 - scc_ast_type_t ptr_to_func_ret_float; - scc_ast_type_pointer_init(&ptr_to_func_ret_float, &func_ret_float); - - // 4) 外层函数类型,返回上述指针,参数为 (int, ...) - scc_ast_decl_t param_int, param_var; - scc_ast_decl_param_init( - ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_param_init(¶m_var, &va_list_type, null); - scc_ast_decl_vec_t params_outer; - scc_vec_init(params_outer); - scc_vec_push(params_outer, ¶m_int); - scc_vec_push(params_outer, ¶m_var); - - scc_ast_type_t outer_func; - scc_ast_type_function_init(&outer_func, &ptr_to_func_ret_float, - ¶ms_outer); - - // 5) 指针指向外层函数 - scc_ast_type_t ptr_to_outer_func; - scc_ast_type_pointer_init(&ptr_to_outer_func, &outer_func); - SCC_CHECK_AST(&ptr_to_outer_func.base, "float (*(*)(int, ...))()", - scc_parse_type_name); - } -} - TEST_LIST = { {"parser_unit", test_parser_unit}, - {"parser_expression", test_parser_expression}, - {"parser_type", test_parser_type}, - // {"parser_statement", test_parser_statement}, - // {"parser_declaration", test_parser_declaration}, - // {"parser_translation_unit", test_parser_translation_unit}, {null, null}, };