From c99f64708ea119d64a3a754fcf1d16e0496fbfbb Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Fri, 13 Mar 2026 13:48:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(parser):=20=E6=94=B9=E8=BF=9B=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=99=A8=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86=E5=92=8C?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在初始化解析中添加缺失的赋值操作符检查 - 改进后缀表达式解析逻辑,处理嵌套情况 - 添加数组下标初始化的赋值操作符验证 - 修复主表达式解析中的返回语句处理 refactor(pproc): 优化预处理器宏展开和位置追踪 - 添加token复制函数来保持原始位置信息 - 重构宏展开函数参数传递方式 - 修复字符串化参数的位置信息处理 - 改进可变参数宏的处理逻辑 test(parser): 增加标签语句和字符串字面量测试用例 - 添加返回语句with复合字面量的测试 - 增加标签继续语句的测试用例 - 添加字符串连接的解析测试 test(pproc): 添加预处理器位置追踪测试 - 增加双重宏定义位置追踪测试 - 添加带参数宏定义位置追踪测试 - 增加字符串化操作位置追踪测试 docs: 更新代码中的宏定义和注释 - 修正未定义标识符的拼写错误 - 添加必要的头文件包含 - 改进错误消息提示文本 --- libs/ast/src/ast_dump.c | 1 + libs/lexer/include/scc_lexer_token.h | 7 +- libs/parser/src/parse_decl.c | 17 ++++- libs/parser/src/parse_expr.c | 47 ++++++++---- libs/parser/src/parse_stmt.c | 4 +- libs/parser/tests/test_parser_unit.c | 24 +++++- libs/pproc/src/pproc_expand.c | 62 ++++++++------- libs/pproc/src/scc_pproc.c | 8 ++ libs/pproc/tests/test_pproc_pos.c | 97 ++++++++++++++++++++++++ libs/pproc/tests/test_pproc_unit.c | 4 + runtime/log/include/log.h | 12 +-- runtime/scc_core/include/scc_core_str.h | 4 + runtime/scc_core/include/scc_core_type.h | 4 + src/main.c | 29 +++++-- 14 files changed, 260 insertions(+), 60 deletions(-) diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 6b9e074..7ca1b03 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -555,6 +555,7 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) { PRINT_VALUE(ctx, " %s", stmt->label_stmt.label); } end_node_dump(ctx); + dump_child_node((scc_ast_node_t *)stmt->label_stmt.stmt, ctx, true); break; case SCC_AST_STMT_COMPOUND: end_node_dump(ctx); diff --git a/libs/lexer/include/scc_lexer_token.h b/libs/lexer/include/scc_lexer_token.h index e101c0e..e2d7b2f 100644 --- a/libs/lexer/include/scc_lexer_token.h +++ b/libs/lexer/include/scc_lexer_token.h @@ -84,7 +84,6 @@ typedef enum scc_cstd { #define SCC_CTOK_TABLE \ X(unknown , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_UNKNOWN ) \ - X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED ) \ X(EOF , SCC_TOK_SUBTYPE_EOF, SCC_TOK_EOF ) \ X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \ X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \ @@ -160,6 +159,12 @@ typedef enum scc_tok_type { #define X(name, subtype, tok, std) tok, SCC_CKEYWORD_TABLE #undef X + + // FIXME hack one bit for disabled +#define X(str, subtype, tok) tok, + X(sum , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_SUM ) + X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED = 1<<7 ) +#undef X } scc_tok_type_t; /* clang-format on */ diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index c226886..788d0ed 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -198,13 +198,21 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_parser_next_consume(parser, null); tok_ptr = scc_parser_peek(parser); if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) { + scc_parser_next(parser); lhs = scc_malloc(sizeof(scc_ast_expr_t)); Assert(lhs != null); scc_ast_expr_member_init(lhs, base, scc_cstring_as_cstr(&tok_ptr->lexeme)); - + if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected '='"); + } rhs = scc_parse_initializer(parser, lhs); - Assert(rhs != null); + if (rhs == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected initializer"); + Panic(); + } scc_vec_push(lhs_exprs, lhs); scc_vec_push(rhs_exprs, rhs); } else { @@ -221,7 +229,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, lhs = scc_malloc(sizeof(scc_ast_expr_t)); Assert(lhs != null); scc_ast_expr_array_subscript_init(lhs, base, idx); - + if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '='"); + } rhs = scc_parse_initializer(parser, lhs); Assert(rhs != null); scc_vec_push(lhs_exprs, lhs); @@ -230,6 +240,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_parser_next_consume(parser, null); break; } else if (tok_ptr->type == SCC_TOK_COMMA) { + scc_parser_next_consume(parser, null); continue; } else { // FIXME diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index e746832..87af9c3 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -480,9 +480,11 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { // 可以嵌套) scc_ast_expr_t *operand = parse_cast_expression(parser); if (!operand) { - // 释放 type - // TODO: 需要 scc_ast_type_drop(type); - return null; + // FIXME postfix-expression + scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_lvalue_init(expr, type); + operand = scc_parse_initializer(parser, expr); + return operand; } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); @@ -576,10 +578,11 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { scc_ast_expr_sizeof_init(null, type); return expr; } else { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected type-name after sizeof"); TODO(); } } - // 否则作为 sizeof unary-expression scc_ast_expr_t *operand = parse_unary_expression(parser); if (!operand) { @@ -612,12 +615,10 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'"); } - if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) { - SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '{"); - } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); scc_ast_expr_lvalue_init(expr, type); - return scc_parse_initializer(parser, expr); + left = scc_parse_initializer(parser, expr); + return left; } while (1) { @@ -779,12 +780,26 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return expr; } case SCC_TOK_STRING_LITERAL: { - if (!scc_parser_next_consume(parser, &tok)) - return null; + scc_cstring_t string = scc_cstring_create(); + scc_lexer_tok_t tok; + while (1) { + tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + break; + } + if (tok_ptr->type != SCC_TOK_STRING_LITERAL) { + break; + } + scc_parser_next_consume(parser, &tok); + scc_cstring_t tmp = scc_cstring_move(&tok.lexeme); + scc_lexer_tok_drop(&tok); + scc_cstring_append(&string, &tmp); + } + expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&tok.lexeme), - false); + scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string), + true); return expr; } case SCC_TOK_L_PAREN: @@ -807,9 +822,11 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) { // 是类型转换,解析后面的 cast-expression scc_ast_expr_t *operand = parse_cast_expression(parser); if (!operand) { - // 释放 type - // TODO: scc_ast_type_drop(type); - return null; + // FIXME postfix-expression + scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_lvalue_init(expr, type); + operand = scc_parse_initializer(parser, expr); + return operand; } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 9ecdf43..48b0572 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -80,7 +80,8 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) { } if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) { - return null; + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected identifier before like `identifier : statement` ."); } scc_ast_stmt_t *statement = scc_parse_statement(parser); @@ -364,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { scc_parser_reset(parser); break; } + scc_parser_reset(parser); stmt = parse_label_statement(parser); goto RETURN; case SCC_TOK_CASE: { diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index 979adc3..d081cc2 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -56,8 +57,9 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) { char *buffer = _buffer; va_list args; va_start(args, fmt); - scc_vsnprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer) - 1, - fmt, args); + int res = scc_vsnprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer) - 1, fmt, args); + Assert(res > 0); va_end(args); } @@ -589,6 +591,24 @@ static void test_parser_unit(void) { SCC_CHECK_AST(&expr.base, "(void){.data = ((void *)0), .size = 0, .cap = 0}", 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_t continue_stmt; + scc_ast_stmt_continue_init(&continue_stmt); + scc_ast_stmt_t stmt; + scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt); + 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); } { diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index 8350f57..f040634 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -6,6 +6,15 @@ static void rescan(scc_pproc_expand_t *expand_ctx, const scc_pproc_macro_t *macro, scc_lexer_tok_vec_t *tok_buffer); +static inline scc_lexer_tok_t scc_pproc_tok_copy(scc_pproc_expand_t *ctx, + const scc_lexer_tok_t *src) { + scc_lexer_tok_t dst = scc_lexer_tok_copy(src); + if (ctx->need_keep_org_pos) { + dst.loc = ctx->call_pos; + } + return dst; +} + static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *arg_tokens) { // WRITE BY AI @@ -13,8 +22,9 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, scc_cstring_append_ch(&str, '\"'); // 左引号 int need_space = 0; // 是否需要插入空格 + scc_lexer_tok_t *tok = null; scc_vec_foreach(*arg_tokens, i) { - scc_lexer_tok_t *tok = &scc_vec_at(*arg_tokens, i); + tok = &scc_vec_at(*arg_tokens, i); if (tok->type == SCC_TOK_BLANK) { need_space = 1; // 标记遇到空白 continue; @@ -39,8 +49,11 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, scc_lexer_tok_t result; result.type = SCC_TOK_STRING_LITERAL; result.lexeme = str; - if (ctx->need_keep_org_pos) + if (ctx->need_keep_org_pos) { result.loc = ctx->call_pos; + } else { + result.loc = tok ? tok->loc : scc_pos_create(); + } return result; } @@ -88,8 +101,9 @@ RETURN: scc_lexer_drop_ring(ring); scc_lexer_drop(&lexer); scc_sstream_drop(&sstream); - if (ctx->need_keep_org_pos) + if (ctx->need_keep_org_pos) { result.loc = ctx->call_pos; + } return result; } @@ -102,6 +116,7 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx, copyed_ctx->macro_table = expand_ctx->macro_table; copyed_ctx->need_rescan = false; copyed_ctx->need_parse_defined = expand_ctx->need_parse_defined; + copyed_ctx->need_keep_org_pos = expand_ctx->need_keep_org_pos; scc_vec_init(copyed_ctx->output); } @@ -394,7 +409,7 @@ static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer, } } -static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, +static inline void expand_function_macro(scc_pproc_expand_t *ctx, const scc_pproc_macro_t *macro) { scc_lexer_tok_vec_t tok_buffer; @@ -403,7 +418,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, Assert(macro->type == SCC_PP_MACRO_FUNCTION); scc_lexer_tok_vec_t raw_args; scc_vec_init(raw_args); - scc_pproc_parse_macro_arguments(expand_ctx->input, &raw_args, false); + scc_pproc_parse_macro_arguments(ctx->input, &raw_args, false); // collect, fill and expand arg scc_pproc_macro_extened_params_t splited_params; @@ -414,15 +429,13 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, scc_pproc_macro_extened_params_t expanded_params; scc_vec_init(expanded_params); - expand_arguments(&expanded_params, &splited_params, expand_ctx); + expand_arguments(&expanded_params, &splited_params, ctx); Assert(scc_vec_size(expanded_params) >= scc_vec_size(macro->params)); // replace scc_vec_foreach(macro->replaces, i) { scc_lexer_tok_t tok = - scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i)); - if (expand_ctx->need_keep_org_pos) - tok.loc = expand_ctx->call_pos; + scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i)); if (tok.type == SCC_TOK_BLANK) { scc_cstring_free(&tok.lexeme); tok.lexeme = scc_cstring_from_cstr(" "); @@ -444,8 +457,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro); Assert(j != -1 && j < (int)scc_vec_size(splited_params)); - tok = - stringify_argument(expand_ctx, &scc_vec_at(splited_params, j)); + tok = stringify_argument(ctx, &scc_vec_at(splited_params, j)); scc_vec_push(tok_buffer, tok); i = right_idx; continue; @@ -468,11 +480,11 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, Assert(idx < (int)scc_vec_size(splited_params)); scc_lexer_tok_vec_t *tok_vec = &scc_vec_at(splited_params, idx); scc_vec_foreach(*tok_vec, j) { - scc_vec_push(right_vec, - scc_lexer_tok_copy(&scc_vec_at(*tok_vec, j))); + scc_vec_push(right_vec, scc_pproc_tok_copy( + ctx, &scc_vec_at(*tok_vec, j))); } } else { - scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok)); + scc_vec_push(right_vec, scc_pproc_tok_copy(ctx, right_tok)); } scc_lexer_tok_t *right = @@ -482,12 +494,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)), "__VA_ARGS__") == 0) { if (scc_vec_size(right_vec) == 0) { - concact(expand_ctx, &tok_buffer, right, true); + concact(ctx, &tok_buffer, right, true); } else { continue; } } else { - concact(expand_ctx, &tok_buffer, right, false); + concact(ctx, &tok_buffer, right, false); } scc_vec_foreach(right_vec, j) { @@ -512,7 +524,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, scc_vec_at(expanded_params, j); scc_lexer_tok_drop(&tok); scc_vec_foreach(expanded_param, k) { - tok = scc_lexer_tok_copy(&scc_vec_at(expanded_param, k)); + tok = + scc_pproc_tok_copy(ctx, &scc_vec_at(expanded_param, k)); scc_vec_push(tok_buffer, tok); } continue; @@ -523,20 +536,18 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, expanded_params_free(&splited_params); expanded_params_free(&expanded_params); - rescan(expand_ctx, macro, &tok_buffer); + rescan(ctx, macro, &tok_buffer); Assert(tok_buffer.cap == 0); // FIXME } -static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, +static inline void expand_object_macro(scc_pproc_expand_t *ctx, const scc_pproc_macro_t *macro) { scc_lexer_tok_vec_t tok_buffer; scc_vec_init(tok_buffer); scc_vec_foreach(macro->replaces, i) { scc_lexer_tok_t tok = - scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i)); - if (expand_ctx->need_keep_org_pos) - tok.loc = expand_ctx->call_pos; + scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i)); if (tok.type == SCC_TOK_BLANK) { // FIXME using function to warpper it scc_cstring_free(&tok.lexeme); @@ -553,14 +564,14 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, right = &scc_vec_at(macro->replaces, right_idx); } - concact(expand_ctx, &tok_buffer, right, false); + concact(ctx, &tok_buffer, right, false); i = right_idx; continue; } scc_vec_push(tok_buffer, tok); } - rescan(expand_ctx, macro, &tok_buffer); + rescan(ctx, macro, &tok_buffer); } static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) { @@ -640,8 +651,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { if (macro == null || need_skip(expand_ctx, macro)) { // FIXME maybe keyword is error or don't parse c keyword or number - // 这个地方不太清楚正确的原因 - tok.type = SCC_TOK_DISABLED; + tok.type += SCC_TOK_DISABLED; scc_vec_push(expand_ctx->output, tok); continue; } diff --git a/libs/pproc/src/scc_pproc.c b/libs/pproc/src/scc_pproc.c index 8641721..66966e0 100644 --- a/libs/pproc/src/scc_pproc.c +++ b/libs/pproc/src/scc_pproc.c @@ -126,6 +126,14 @@ static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) { cbool ret = false; CONTINUE: ret = pproc_next(pp, tok); + // FIXME Hack the token + if (ret && tok->type >= SCC_TOK_DISABLED) { + tok->type -= SCC_TOK_DISABLED; + } + + if (ret && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_INVALID) { + PanicFmt("Invalid token: %s", scc_cstring_as_cstr(&tok->lexeme)); + } if (ret && !pp->ring_need_comment && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_COMMENT) { scc_lexer_tok_drop(tok); diff --git a/libs/pproc/tests/test_pproc_pos.c b/libs/pproc/tests/test_pproc_pos.c index 8acb6ab..29633d7 100644 --- a/libs/pproc/tests/test_pproc_pos.c +++ b/libs/pproc/tests/test_pproc_pos.c @@ -34,8 +34,105 @@ static void test_define_pos(void) { scc_sstream_drop(&mem_stream); } +static void test_define_double_pos(void) { + int ret = 0; + scc_sstream_t mem_stream; + const char *input = "#define _OBJ 1\n#define OBJ _OBJ\nOBJ"; + ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(ret == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_pproc_t pp; + scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); + + scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true); + scc_lexer_tok_t tok = {0}; + + scc_ring_next_consume(*tok_ring, tok, ret); + Assert(ret == true); + TEST_CHECK(tok.loc.line == 3 && tok.loc.col == 1 && + scc_strcmp(tok.lexeme.data, "1") == 0); + TEST_MSG("Expected: %d:%d:%s", 3, 1, "1"); + TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col, + tok.lexeme.data); + + scc_ring_free(*tok_ring); + scc_pproc_drop(&pp); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); +} + +static void test_define_param_pos(void) { + int ret = 0; + scc_sstream_t mem_stream; + const char *input = "#define OBJ 1\n#define func(x) x\nfunc(OBJ)"; + ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(ret == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_pproc_t pp; + scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); + + scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true); + scc_lexer_tok_t tok = {0}; + + scc_ring_next_consume(*tok_ring, tok, ret); + Assert(ret == true); + TEST_CHECK(tok.loc.line == 3 && tok.loc.col == 1 && + scc_strcmp(tok.lexeme.data, "1") == 0); + TEST_MSG("Expected: %d:%d:%s", 3, 1, "1"); + TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col, + tok.lexeme.data); + + scc_ring_free(*tok_ring); + scc_pproc_drop(&pp); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); +} + +static void test_define_stringify_pos(void) { + int ret = 0; + scc_sstream_t mem_stream; + const char *input = + "#define _STR(x) #x\n#define STR(x) _STR(x)\n#define OBJ 1\nSTR(OBJ)"; + ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(ret == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_pproc_t pp; + scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); + + scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true); + scc_lexer_tok_t tok = {0}; + + scc_ring_next_consume(*tok_ring, tok, ret); + Assert(ret == true); + TEST_CHECK(tok.loc.line == 4 && tok.loc.col == 1 && + scc_strcmp(tok.lexeme.data, "\"1\"") == 0); + TEST_MSG("Expected: %d:%d:%s", 4, 1, "\"1\""); + TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col, + tok.lexeme.data); + + scc_ring_free(*tok_ring); + scc_pproc_drop(&pp); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); +} + #define TEST_LIST_CASE(func_name) {#func_name, func_name} TEST_LIST = { TEST_LIST_CASE(test_define_pos), + TEST_LIST_CASE(test_define_double_pos), + TEST_LIST_CASE(test_define_param_pos), + TEST_LIST_CASE(test_define_stringify_pos), {NULL, NULL}, }; diff --git a/libs/pproc/tests/test_pproc_unit.c b/libs/pproc/tests/test_pproc_unit.c index 8fd8d9d..82fd6d9 100644 --- a/libs/pproc/tests/test_pproc_unit.c +++ b/libs/pproc/tests/test_pproc_unit.c @@ -541,6 +541,8 @@ static void test_gnu_comma_variadic_deletion(void) { "printf(\"%d\",42)\n"); } +static void test_real_case(void) {} + static void test_c99_docs(void) { TEST_CASE("6.10.3.3 The ## operator EXAMPLE"); CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n" @@ -644,6 +646,8 @@ TEST_LIST = { TEST_LIST_CASE(test_variadic_macros), TEST_LIST_CASE(test_gnu_comma_variadic_deletion), + TEST_LIST_CASE(test_real_case), + TEST_LIST_CASE(test_c99_docs), {NULL, NULL}, }; diff --git a/runtime/log/include/log.h b/runtime/log/include/log.h index 8b8d5d7..0efad5b 100644 --- a/runtime/log/include/log.h +++ b/runtime/log/include/log.h @@ -18,13 +18,13 @@ #endif #ifdef __GNUC__ // GCC, Clang -#define __smcc_log_unreachable() (__builtin_unreachable()) +#define __scc_log_unreachable() (__builtin_unreachable()) #elif defined _MSC_VER // MSVC -#define __smcc_log_unreachable() (__assume(false)) -#elif defined __SCC_BUILT_IN__ // The SCC Compiler (my compiler) -#define __smcc_log_unreachable() (__smcc_builtin_unreachable()) +#define __scc_log_unreachable() (__assume(false)) +#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler) +#define __scc_log_unreachable() (__scc_builtin_unreachable()) #else -#define __smcc_log_unreachable() +#define __scc_log_unreachable() ((void)0) #endif #ifndef log_vsnprintf @@ -155,7 +155,7 @@ void log_set_handler(logger_t *logger, log_handler handler); ((void)((cond) || \ (__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \ &__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \ - log_exit(1), __smcc_log_unreachable(), 0))) + log_exit(1), __scc_log_unreachable(), 0))) /// @name 断言工具宏 /// @{ diff --git a/runtime/scc_core/include/scc_core_str.h b/runtime/scc_core/include/scc_core_str.h index 1f32c08..50b923c 100644 --- a/runtime/scc_core/include/scc_core_str.h +++ b/runtime/scc_core/include/scc_core_str.h @@ -211,4 +211,8 @@ static inline char *scc_cstring_move_cstr(scc_cstring_t *str) { return ret; } +static inline scc_cstring_t scc_cstring_move(scc_cstring_t *str) { + return scc_cstring_from_cstr(scc_cstring_move_cstr(str)); +} + #endif /* __SCC_CORE_STR_H__ */ diff --git a/runtime/scc_core/include/scc_core_type.h b/runtime/scc_core/include/scc_core_type.h index e844eee..c828c7c 100644 --- a/runtime/scc_core/include/scc_core_type.h +++ b/runtime/scc_core/include/scc_core_type.h @@ -58,6 +58,10 @@ typedef double f64; typedef bool cbool; +#ifndef null +#define null NULL +#endif + /* clang-format on */ #endif diff --git a/src/main.c b/src/main.c index 23d05ef..bfa802a 100644 --- a/src/main.c +++ b/src/main.c @@ -226,12 +226,18 @@ int main(int argc, const char **argv, const char **envp) { LOG_FATAL("Failed to open file %s", config.output_file); return 1; } + } else { + fp = scc_stdout; } } + int error_code = 0; + cbool need_end = false; scc_sstream_t sstream; - if (scc_sstream_init(&sstream, config.input_file, 1024)) { - return 0; + error_code = scc_sstream_init(&sstream, config.input_file, 1024); + if (error_code) { + goto sstream_drop; + need_end = true; } scc_lexer_t lexer; @@ -244,11 +250,14 @@ int main(int argc, const char **argv, const char **envp) { } else { print_file(tok_ring, fp); } - return 0; + need_end = true; + goto lexer_drop; } scc_pproc_t pproc; scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true)); + // FIXME maybe using config to got download path and add include path + scc_pproc_add_include_path_cstr(&pproc, "./.scc_include"); scc_vec_foreach(config.include_paths, i) { scc_pproc_add_include_path_cstr(&pproc, scc_vec_at(config.include_paths, i)); @@ -266,10 +275,12 @@ int main(int argc, const char **argv, const char **envp) { } else { print_file(tok_ring, fp); } - return 0; + need_end = true; + goto pproc_drop; } - scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pproc, 8, false, false); + scc_lexer_tok_ring_t *tok_ring = + scc_pproc_to_ring(&pproc, 1024, false, false); scc_parser_t parser; scc_sema_callbacks_t sema_callbacks; scc_sema_init(&sema_callbacks); @@ -279,9 +290,15 @@ int main(int argc, const char **argv, const char **envp) { scc_sema_drop(&sema_callbacks); scc_parser_drop(&parser); +pproc_drop: scc_pproc_drop(&pproc); +lexer_drop: scc_lexer_drop(&lexer); +sstream_drop: scc_sstream_drop(&sstream); + if (error_code || need_end) { + return error_code; + } if (config.emit_ast) { scc_tree_dump_ctx_t tree_dump; @@ -312,6 +329,6 @@ int main(int argc, const char **argv, const char **envp) { // return 0; // } - scc_printf("output exe at %s", config.output_file); + scc_printf("output exe at %s\n", config.output_file); return 0; }