- 在初始化解析中添加缺失的赋值操作符检查 - 改进后缀表达式解析逻辑,处理嵌套情况 - 添加数组下标初始化的赋值操作符验证 - 修复主表达式解析中的返回语句处理 refactor(pproc): 优化预处理器宏展开和位置追踪 - 添加token复制函数来保持原始位置信息 - 重构宏展开函数参数传递方式 - 修复字符串化参数的位置信息处理 - 改进可变参数宏的处理逻辑 test(parser): 增加标签语句和字符串字面量测试用例 - 添加返回语句with复合字面量的测试 - 增加标签继续语句的测试用例 - 添加字符串连接的解析测试 test(pproc): 添加预处理器位置追踪测试 - 增加双重宏定义位置追踪测试 - 添加带参数宏定义位置追踪测试 - 增加字符串化操作位置追踪测试 docs: 更新代码中的宏定义和注释 - 修正未定义标识符的拼写错误 - 添加必要的头文件包含 - 改进错误消息提示文本
179 lines
5.2 KiB
C
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);
|
|
}
|