feat(pproc): 修改宏展开器以支持连续函数式宏调用

修改了预处理器宏展开功能,将输出类型从环形缓冲区改为向量,
并实现了对连续函数式宏调用的支持。现在可以正确处理像
g(z) -> f(x * (z)) 这样的宏替换场景,其中标识符可能被重新
定义为新的函数式宏。

BREAKING CHANGE: 函数签名 scc_pproc_expand_by_vec 的输出参数
从 scc_lexer_tok_ring_t* 改为 scc_lexer_tok_vec_t*
This commit is contained in:
zzy
2026-03-01 14:23:17 +08:00
parent 8cbb9e6987
commit 60cdfd2c33
4 changed files with 67 additions and 12 deletions

View File

@@ -29,7 +29,7 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
const scc_pproc_macro_t *macro); const scc_pproc_macro_t *macro);
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
scc_lexer_tok_vec_t *input, scc_lexer_tok_vec_t *input,
scc_lexer_tok_ring_t *output, scc_lexer_tok_vec_t *output,
cbool need_parse_defined); cbool need_parse_defined);
#endif /* __SCC_PPROC_EXPAND_H__ */ #endif /* __SCC_PPROC_EXPAND_H__ */

View File

@@ -168,8 +168,10 @@ static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp,
if (tok.type == SCC_TOK_ENDLINE) if (tok.type == SCC_TOK_ENDLINE)
break; break;
} }
scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, out_ring, scc_lexer_tok_vec_t out_vec;
scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, &out_vec,
need_parse_defined); need_parse_defined);
*out_ring = scc_lexer_array_to_ring(&out_vec);
} }
/* /*

View File

@@ -2,6 +2,10 @@
#include <scc_lexer_utils.h> #include <scc_lexer_utils.h>
#include <scc_pproc.h> #include <scc_pproc.h>
static void rescan(scc_pproc_expand_t *expand_ctx,
const scc_pproc_macro_t *macro,
scc_lexer_tok_vec_t *tok_buffer);
static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) { static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
// WRITE BY AI // WRITE BY AI
scc_cstring_t str = scc_cstring_create(); scc_cstring_t str = scc_cstring_create();
@@ -104,13 +108,26 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
scc_vec_push(expaned_buffer, tok); scc_vec_push(expaned_buffer, tok);
scc_pproc_parse_macro_arguments(input, &expaned_buffer, true); scc_pproc_parse_macro_arguments(input, &expaned_buffer, true);
} }
while (1) {
scc_ring_peek(*input, tok, ok);
if (ok == false) {
break;
}
if (tok.type == SCC_TOK_L_PAREN) {
scc_pproc_parse_macro_arguments(input, &expaned_buffer, true);
} else {
break;
}
}
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, output, false); scc_lexer_tok_vec_t output_vec;
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false);
*output = scc_lexer_array_to_ring(&output_vec);
} }
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
scc_lexer_tok_vec_t *input, scc_lexer_tok_vec_t *input,
scc_lexer_tok_ring_t *output, scc_lexer_tok_vec_t *output,
cbool need_parse_defined) { cbool need_parse_defined) {
scc_pproc_expand_t ctx; scc_pproc_expand_t ctx;
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input); scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input);
@@ -124,7 +141,7 @@ void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
scc_pproc_marco_table_init(ctx.expanded_set); scc_pproc_marco_table_init(ctx.expanded_set);
scc_pproc_expand_macro(&ctx); scc_pproc_expand_macro(&ctx);
*output = scc_lexer_array_to_ring(&ctx.output); *output = ctx.output;
scc_pproc_macro_table_drop(ctx.expanded_set); scc_pproc_macro_table_drop(ctx.expanded_set);
} }
@@ -240,17 +257,51 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
scc_lexer_tok_vec_t *tok_buffer) { scc_lexer_tok_vec_t *tok_buffer) {
scc_pproc_expand_t rescan_ctx; scc_pproc_expand_t rescan_ctx;
disable(expand_ctx, macro);
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer); scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer);
scc_copy_expand(expand_ctx, &rescan_ctx, &ring); scc_copy_expand(expand_ctx, &rescan_ctx, &ring);
disable(expand_ctx, macro);
scc_pproc_expand_macro(&rescan_ctx); scc_pproc_expand_macro(&rescan_ctx);
enable(expand_ctx, macro);
scc_ring_free(ring); scc_ring_free(ring);
scc_vec_foreach(rescan_ctx.output, i) { scc_vec_foreach(rescan_ctx.output, i) {
scc_vec_push(expand_ctx->output, scc_vec_at(rescan_ctx.output, i)); scc_vec_push(expand_ctx->output, scc_vec_at(rescan_ctx.output, i));
} }
enable(expand_ctx, macro); if (scc_vec_size(expand_ctx->output) == 0) {
return;
}
scc_lexer_tok_t *end_tok =
&scc_vec_at(expand_ctx->output, scc_vec_size(expand_ctx->output) - 1);
if (scc_get_tok_subtype(end_tok->type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
return;
}
scc_pproc_macro_t *end_macro =
scc_pproc_macro_table_get(expand_ctx->macro_table, &end_tok->lexeme);
if (end_macro == null || end_macro->type != SCC_PP_MACRO_FUNCTION) {
return;
}
int ok = false;
scc_lexer_tok_t tok;
scc_ring_peek(*expand_ctx->input, tok, ok);
if (ok && tok.type == SCC_TOK_L_PAREN) {
scc_lexer_tok_vec_t expaned_buffer;
scc_vec_init(expaned_buffer);
scc_vec_push(expaned_buffer, scc_vec_pop(expand_ctx->output));
scc_pproc_parse_macro_arguments(expand_ctx->input, &expaned_buffer,
true);
scc_lexer_tok_vec_t output = {0};
scc_pproc_expand_by_vec(expand_ctx->macro_table, &expaned_buffer,
&output, expand_ctx->need_parse_defined);
scc_vec_foreach(output, i) {
scc_vec_push(expand_ctx->output, scc_vec_at(output, i));
}
}
} }
static int find_params(const scc_lexer_tok_t *tok, static int find_params(const scc_lexer_tok_t *tok,

View File

@@ -172,10 +172,12 @@ static void test_define_nested_macros(void) {
"f(x(0) * (f(x(0) * (x(0)))))\n" "f(x(0) * (f(x(0) * (x(0)))))\n"
"f(x(0) * (f(x(0) * (a))))\n"); "f(x(0) * (f(x(0) * (a))))\n");
TEST_CASE("NO NAME"); TEST_CASE("replace got new function-like macro");
CHECK_PP_OUTPUT_EXACT("#define f() int\n" CHECK_PP_OUTPUT_EXACT("#define f(a) f(x * (a))\n"
"f()\n", "#define g f\n"
"int\n"); "#define x 2\n"
"g(z)\n",
"f(2 * (z))\n");
} }
static void test_undef_macros(void) { static void test_undef_macros(void) {