feat(ast): 添加复合表达式和初始化器解析支持

重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND,
更新相关结构体定义以支持复合字面量的左右表达式向量表示。

添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能,
包括大括号初始化列表、成员访问和数组下标的处理逻辑。

更新表达式解析器为基于优先级的递归下降解析,修复变量声明中
初始化表达式的内存泄漏问题。

完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
This commit is contained in:
zzy
2026-03-12 21:14:08 +08:00
parent b00a42a539
commit c46578736a
15 changed files with 495 additions and 225 deletions

View File

@@ -11,8 +11,10 @@ typedef struct {
scc_pproc_macro_table_t *expanded_set;
scc_lexer_tok_ring_t *input;
scc_lexer_tok_vec_t output;
scc_pos_t call_pos;
cbool need_rescan;
cbool need_parse_defined;
cbool need_keep_org_pos;
} scc_pproc_expand_t;
static inline scc_lexer_tok_ring_t
@@ -27,10 +29,11 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx);
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
scc_lexer_tok_ring_t *input,
scc_lexer_tok_ring_t *output,
const scc_pproc_macro_t *macro);
const scc_pproc_macro_t *macro,
cbool need_keep_org_pos);
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
scc_lexer_tok_vec_t *input,
scc_lexer_tok_vec_t *output,
cbool need_parse_defined);
cbool need_parse_defined, cbool need_keep_org_pos);
#endif /* __SCC_PPROC_EXPAND_H__ */

View File

@@ -51,6 +51,7 @@ typedef struct scc_pproc {
struct {
int max_include_depth;
cbool keep_original_pos;
} config;
} scc_pproc_t;

View File

@@ -176,7 +176,7 @@ static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp,
}
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, pp->config.keep_original_pos);
*out_ring = scc_lexer_array_to_ring(&out_vec);
}

View File

@@ -6,7 +6,8 @@ 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_pproc_expand_t *ctx,
scc_lexer_tok_vec_t *arg_tokens) {
// WRITE BY AI
scc_cstring_t str = scc_cstring_create();
scc_cstring_append_ch(&str, '\"'); // 左引号
@@ -38,10 +39,13 @@ static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
scc_lexer_tok_t result;
result.type = SCC_TOK_STRING_LITERAL;
result.lexeme = str;
if (ctx->need_keep_org_pos)
result.loc = ctx->call_pos;
return result;
}
static scc_lexer_tok_t concatenate_tokens(const scc_lexer_tok_t *left,
static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx,
const scc_lexer_tok_t *left,
const scc_lexer_tok_t *right) {
scc_cstring_t new_lex = scc_cstring_from_cstr("");
if (left != null) {
@@ -84,6 +88,8 @@ RETURN:
scc_lexer_drop_ring(ring);
scc_lexer_drop(&lexer);
scc_sstream_drop(&sstream);
if (ctx->need_keep_org_pos)
result.loc = ctx->call_pos;
return result;
}
@@ -102,7 +108,8 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx,
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
scc_lexer_tok_ring_t *input,
scc_lexer_tok_ring_t *output,
const scc_pproc_macro_t *macro) {
const scc_pproc_macro_t *macro,
cbool need_keep_org_pos) {
scc_lexer_tok_vec_t expaned_buffer;
scc_vec_init(expaned_buffer);
@@ -130,7 +137,8 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
}
scc_lexer_tok_vec_t output_vec;
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false);
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
need_keep_org_pos);
Assert(output->cap == 0 && output->data == null); // FIXME hack it
*output = scc_lexer_array_to_ring(&output_vec);
}
@@ -138,13 +146,16 @@ void scc_pproc_expand_by_src(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 *output,
cbool need_parse_defined) {
cbool need_parse_defined,
cbool need_keep_org_pos) {
scc_pproc_expand_t ctx;
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input);
ctx.input = ˚
ctx.macro_table = macro_table;
ctx.need_rescan = false;
ctx.need_parse_defined = need_parse_defined;
ctx.need_keep_org_pos = need_keep_org_pos;
ctx.call_pos = scc_pos_create();
scc_vec_init(ctx.output);
scc_pproc_macro_table_t expanded_set;
ctx.expanded_set = &expanded_set;
@@ -311,7 +322,8 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
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);
&output, expand_ctx->need_parse_defined,
expand_ctx->need_keep_org_pos);
scc_vec_foreach(output, i) {
scc_vec_push(expand_ctx->output, scc_vec_at(output, i));
}
@@ -352,8 +364,8 @@ static inline int got_right_non_blank(int i,
return right_idx;
}
static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right,
cbool gnu_va_arg_extend) {
static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
scc_lexer_tok_t *right, cbool gnu_va_arg_extend) {
// ## contact
int tok_buf_size = (int)scc_vec_size(*tok_buffer);
int left_idx = got_left_non_blank(tok_buf_size, tok_buffer);
@@ -369,7 +381,7 @@ static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right,
}
}
scc_lexer_tok_t concate_tok = concatenate_tokens(left, right);
scc_lexer_tok_t concate_tok = concatenate_tokens(ctx, left, right);
while (left_idx++ < tok_buf_size) {
scc_lexer_tok_drop(&scc_vec_pop(*tok_buffer));
@@ -409,6 +421,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
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;
if (tok.type == SCC_TOK_BLANK) {
scc_cstring_free(&tok.lexeme);
tok.lexeme = scc_cstring_from_cstr(" ");
@@ -430,7 +444,8 @@ 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(&scc_vec_at(splited_params, j));
tok =
stringify_argument(expand_ctx, &scc_vec_at(splited_params, j));
scc_vec_push(tok_buffer, tok);
i = right_idx;
continue;
@@ -467,12 +482,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(&tok_buffer, right, true);
concact(expand_ctx, &tok_buffer, right, true);
} else {
continue;
}
} else {
concact(&tok_buffer, right, false);
concact(expand_ctx, &tok_buffer, right, false);
}
scc_vec_foreach(right_vec, j) {
@@ -520,6 +535,8 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
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;
if (tok.type == SCC_TOK_BLANK) {
// FIXME using function to warpper it
scc_cstring_free(&tok.lexeme);
@@ -536,7 +553,7 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
right = &scc_vec_at(macro->replaces, right_idx);
}
concact(&tok_buffer, right, false);
concact(expand_ctx, &tok_buffer, right, false);
i = right_idx;
continue;
}
@@ -630,6 +647,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
}
expand_ctx->need_rescan = true;
expand_ctx->call_pos = tok.loc;
if (macro->type == SCC_PP_MACRO_OBJECT) {
scc_lexer_tok_drop(&tok);
expand_object_macro(expand_ctx, macro);

View File

@@ -62,7 +62,8 @@ CONTINUE:
return ok;
}
scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring,
&pp->expanded_ring, macro);
&pp->expanded_ring, macro,
pp->config.keep_original_pos);
goto CONTINUE;
} else {
// continue
@@ -113,6 +114,7 @@ void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) {
pp->enable = true;
pp->config.max_include_depth = 32;
pp->config.keep_original_pos = true;
}
void scc_pproc_add_builtin_macros() {

View File

@@ -0,0 +1,41 @@
#include <assert.h>
#include <scc_pproc.h>
#include <string.h>
#include <utest/acutest.h>
static void test_define_pos(void) {
int ret = 0;
scc_sstream_t mem_stream;
const char *input = "#define OBJ 1\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 == 2 && tok.loc.col == 1 &&
scc_strcmp(tok.lexeme.data, "1") == 0);
TEST_MSG("Expected: %d:%d:%s", 2, 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),
{NULL, NULL},
};