feat(ast): 添加复合表达式和初始化器解析支持
重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND, 更新相关结构体定义以支持复合字面量的左右表达式向量表示。 添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能, 包括大括号初始化列表、成员访问和数组下标的处理逻辑。 更新表达式解析器为基于优先级的递归下降解析,修复变量声明中 初始化表达式的内存泄漏问题。 完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
This commit is contained in:
@@ -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__ */
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef struct scc_pproc {
|
||||
|
||||
struct {
|
||||
int max_include_depth;
|
||||
cbool keep_original_pos;
|
||||
} config;
|
||||
} scc_pproc_t;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
41
libs/pproc/tests/test_pproc_pos.c
Normal file
41
libs/pproc/tests/test_pproc_pos.c
Normal 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},
|
||||
};
|
||||
Reference in New Issue
Block a user