Files
scc/libs/pproc/src/scc_pproc.c
zzy c99f64708e feat(parser): 改进解析器错误处理和表达式解析逻辑
- 在初始化解析中添加缺失的赋值操作符检查
- 改进后缀表达式解析逻辑,处理嵌套情况
- 添加数组下标初始化的赋值操作符验证
- 修复主表达式解析中的返回语句处理

refactor(pproc): 优化预处理器宏展开和位置追踪

- 添加token复制函数来保持原始位置信息
- 重构宏展开函数参数传递方式
- 修复字符串化参数的位置信息处理
- 改进可变参数宏的处理逻辑

test(parser): 增加标签语句和字符串字面量测试用例

- 添加返回语句with复合字面量的测试
- 增加标签继续语句的测试用例
- 添加字符串连接的解析测试

test(pproc): 添加预处理器位置追踪测试

- 增加双重宏定义位置追踪测试
- 添加带参数宏定义位置追踪测试
- 增加字符串化操作位置追踪测试

docs: 更新代码中的宏定义和注释

- 修正未定义标识符的拼写错误
- 添加必要的头文件包含
- 改进错误消息提示文本
2026-03-13 13:48:55 +08:00

179 lines
5.2 KiB
C

#include <pproc_expand.h>
#include <scc_lexer.h>
#include <scc_lexer_utils.h>
#include <scc_pproc.h>
static int pproc_next_one_file(scc_pproc_t *pp, scc_lexer_tok_t *out) {
scc_lexer_tok_ring_t *stream = null;
scc_lexer_tok_t tok = {0};
int ok = 0;
CONTINUE:
stream = pp->cur_ring;
if (pp->expanded_ring.cap) {
scc_ring_next_consume(pp->expanded_ring, *out, ok);
if (ok == false) {
scc_ring_free(pp->expanded_ring);
goto CONTINUE;
} else {
return true;
}
}
scc_ring_peek(*stream, tok, ok);
if (ok == false) {
return false;
}
if (pp->at_line_start) {
if (tok.type == SCC_TOK_SHARP) {
// parse to #
scc_pproc_handle_directive(pp);
pp->at_line_start = true;
goto CONTINUE;
} else if (tok.type == SCC_TOK_BLANK) {
scc_ring_next(*stream, *out, ok);
scc_ring_peek(*stream, tok, ok);
if (ok && tok.type == SCC_TOK_SHARP) {
scc_lexer_tok_drop(out);
scc_pproc_handle_directive(pp);
pp->at_line_start = true;
goto CONTINUE;
}
scc_ring_back(*stream, ok);
Assert(ok == true);
scc_ring_peek(*stream, tok, ok);
}
}
if (pp->enable == false) {
scc_lexer_skip_until_newline(stream);
pp->at_line_start = true;
goto CONTINUE;
}
if (tok.type == SCC_TOK_ENDLINE) {
scc_ring_next_consume(*stream, *out, ok);
pp->at_line_start = true;
return true;
} else if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_IDENTIFIER) {
// maybe expanded
scc_pproc_macro_t *macro =
scc_pproc_macro_table_get(&pp->macro_table, &tok.lexeme);
if (macro == null) {
scc_ring_next_consume(*stream, *out, ok);
return ok;
}
scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring,
&pp->expanded_ring, macro,
pp->config.keep_original_pos);
goto CONTINUE;
} else {
// continue
scc_ring_next_consume(*stream, *out, ok);
return ok;
}
return false;
}
static int pproc_next(scc_pproc_t *pp, scc_lexer_tok_t *tok) {
int ret = 0;
CONTINUE:
ret = pproc_next_one_file(pp, tok);
if (ret != 0) {
return true;
}
if (scc_vec_size(pp->file_stack) == 0) {
return false;
}
scc_pproc_file_t *file = scc_vec_pop(pp->file_stack);
Assert(file->ring == pp->cur_ring);
scc_lexer_drop_ring(file->ring);
scc_lexer_drop(&(file->lexer));
scc_sstream_drop(&(file->sstream));
scc_free(file);
if (scc_vec_size(pp->file_stack) == 0) {
pp->cur_ring = pp->org_ring;
} else {
pp->cur_ring =
scc_vec_at(pp->file_stack, scc_vec_size(pp->file_stack) - 1)->ring;
}
goto CONTINUE;
}
void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) {
Assert(pp != null && input != null);
pp->org_ring = input;
pp->cur_ring = pp->org_ring;
scc_ring_init(pp->expanded_ring, 0, 0, 0);
scc_pproc_marco_table_init(&pp->macro_table);
scc_vec_init(pp->include_paths);
scc_vec_init(pp->if_stack);
scc_vec_init(pp->file_stack);
pp->at_line_start = true;
pp->enable = true;
pp->config.max_include_depth = 32;
pp->config.keep_original_pos = true;
}
void scc_pproc_add_builtin_macros() {
// TODO
}
static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) {
scc_pproc_t *pp = 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);
goto CONTINUE;
}
if (ret && !pp->ring_need_empty &&
scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_EMPTYSPACE) {
scc_lexer_tok_drop(tok);
goto CONTINUE;
}
return ret;
}
scc_lexer_tok_ring_t *scc_pproc_to_ring(scc_pproc_t *pp, int ring_size,
cbool need_empty, cbool need_comment) {
scc_ring_init(pp->ring, ring_size, fill_token, pp);
pp->ring_need_comment = need_comment;
pp->ring_need_empty = need_empty;
pp->ring_ref_count++;
return &pp->ring;
}
// 销毁预处理器
void scc_pproc_drop(scc_pproc_t *pp) {
if (pp == null)
return;
Assert(pp->cur_ring == pp->org_ring);
scc_lexer_drop_ring(pp->org_ring);
scc_pproc_macro_table_drop(&pp->macro_table);
scc_ring_free(pp->expanded_ring);
scc_vec_foreach(pp->include_paths, i) {
scc_cstring_free(&scc_vec_at(pp->include_paths, i));
}
scc_vec_free(pp->include_paths);
Assert(scc_vec_size(pp->if_stack) == 0);
scc_vec_free(pp->if_stack);
Assert(scc_vec_size(pp->file_stack) == 0);
scc_vec_free(pp->file_stack);
}