feat(lex_parser, pprocessor): replace consume with next and remove stream resets

- Replace `scc_probe_stream_consume` with `scc_probe_stream_next` for consistent stream advancement
- Remove redundant `scc_probe_stream_reset` calls before peeking, as `next` and `peek` handle state
- Update `scc_cstring_new` to `scc_cstring_create` and `scc_pos_init` to `scc_pos_create` for naming consistency
- Change `scc_pp_macro_get` parameter to `const scc_cstring_t*` for better const-correctness
- Improves code clarity and maintains proper stream position tracking
This commit is contained in:
zzy
2025-12-28 10:49:29 +08:00
parent 07f5d9331b
commit 09f4ac8de0
20 changed files with 445 additions and 262 deletions

View File

@@ -8,6 +8,7 @@
typedef enum {
SCC_PP_MACRO_OBJECT, // 对象宏
SCC_PP_MACRO_FUNCTION, // 函数宏
SCC_PP_MACRO_NONE, // 不是宏
} scc_pp_macro_type_t;
typedef SCC_VEC(scc_cstring_t) scc_pp_macro_list_t;
@@ -79,7 +80,7 @@ scc_pp_macro_t *scc_pp_macro_table_set(scc_pp_macro_table_t *pp,
* @return 找到的宏对象指针未找到返回NULL
*/
scc_pp_macro_t *scc_pp_macro_table_get(scc_pp_macro_table_t *pp,
scc_cstring_t *name);
const scc_cstring_t *name);
/**
* @brief 从预处理器中删除宏

View File

@@ -4,22 +4,22 @@
/* clang-format off */
/// https://cppreference.cn/w/c/preprocessor
#define SCC_PP_INST_TOKEN \
X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \
X(elif , SCC_PP_STD, SCC_PP_TOK_UNDEF ) \
X(elifdef , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \
X(elifndef , SCC_PP_STD, SCC_PP_TOK_IF ) \
X(else , SCC_PP_STD, SCC_PP_TOK_IFDEF ) \
X(embed , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \
X(endif , SCC_PP_STD, SCC_PP_TOK_ELSE ) \
X(error , SCC_PP_STD, SCC_PP_TOK_ELIF ) \
X(if , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \
X(ifdef , SCC_PP_C23, SCC_PP_TOK_ELIFNDEF ) \
X(ifndef , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \
X(include , SCC_PP_STD, SCC_PP_TOK_LINE ) \
X(line , SCC_PP_C23, SCC_PP_TOK_EMBED ) \
X(pragma , SCC_PP_STD, SCC_PP_TOK_ERROR ) \
X(undef , SCC_PP_C23, SCC_PP_TOK_WARNING ) \
X(warning , SCC_PP_STD, SCC_PP_TOK_PRAMA ) \
X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \
X(elif , SCC_PP_STD, SCC_PP_TOK_ELIF ) \
X(elifdef , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \
X(elifndef , SCC_PP_STD, SCC_PP_TOK_ELIFNDEF ) \
X(else , SCC_PP_STD, SCC_PP_TOK_ELSE ) \
X(embed , SCC_PP_STD, SCC_PP_TOK_EMBED ) \
X(endif , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \
X(error , SCC_PP_STD, SCC_PP_TOK_ERROR ) \
X(if , SCC_PP_STD, SCC_PP_TOK_IF ) \
X(ifdef , SCC_PP_C23, SCC_PP_TOK_IFDEF ) \
X(ifndef , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \
X(include , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \
X(line , SCC_PP_C23, SCC_PP_TOK_LINE ) \
X(pragma , SCC_PP_STD, SCC_PP_TOK_PRAGMA ) \
X(undef , SCC_PP_C23, SCC_PP_TOK_UNDEF ) \
X(warning , SCC_PP_STD, SCC_PP_TOK_WARNING ) \
// END
/* clang-format on */

View File

@@ -4,7 +4,7 @@
#include <pp_parse.h>
static inline void scc_generate_cstr(scc_cstring_t *buff) {
scc_cstring_t out_buff = scc_cstring_new();
scc_cstring_t out_buff = scc_cstring_create();
scc_cstring_append_ch(&out_buff, '\"');
// TODO it is too simple
scc_cstring_append(&out_buff, buff);
@@ -34,7 +34,7 @@ static inline void scc_generate_cstr(scc_cstring_t *buff) {
scc_cstring_append(out_buff, &scc_vec_at(*list, font)); \
}
// for # ## to generator string
static inline cbool scc_pp_expand_string_unsafe(scc_pp_macro_list_t *list,
static inline cbool scc_pp_expand_string_unsafe(const scc_pp_macro_list_t *list,
scc_cstring_t *out_buff) {
for (usize i = 0; i < list->size; ++i) {
if (SCC_PP_IS_LIST_BLANK(i + 1)) {
@@ -52,7 +52,7 @@ static inline cbool scc_pp_expand_string_unsafe(scc_pp_macro_list_t *list,
if (i < list->size) {
scc_generate_cstr(&scc_vec_at(*list, i));
} else {
LOG_WARN("# need a valid literator");
LOG_ERROR("# need a valid literator");
break;
}
}
@@ -62,7 +62,7 @@ static inline cbool scc_pp_expand_string_unsafe(scc_pp_macro_list_t *list,
}
// 展开对象宏
cbool scc_pp_expand_object_macro(scc_pp_macro_t *macro,
cbool scc_pp_expand_object_macro(const scc_pp_macro_t *macro,
scc_cstring_t *out_buff) {
Assert(macro->type == SCC_PP_MACRO_OBJECT && macro->params.size == 0);
Assert(scc_cstring_is_empty(out_buff) == true);
@@ -72,14 +72,14 @@ cbool scc_pp_expand_object_macro(scc_pp_macro_t *macro,
}
// 展开函数宏
cbool scc_pp_expand_function_macro(scc_pp_macro_t *macro,
scc_pp_macro_list_t *origin_params,
cbool scc_pp_expand_function_macro(const scc_pp_macro_t *macro,
const scc_pp_macro_list_t *origin_params,
scc_pp_macro_list_t *params,
scc_cstring_t *out_buff) {
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
Assert(out_buff != null);
Assert(scc_cstring_is_empty(out_buff) == true);
Assert(params->size == macro->params.size);
Assert(params->size == macro->params.size || params->size == 0);
scc_pp_macro_list_t list;
scc_vec_init(list);
@@ -88,11 +88,16 @@ cbool scc_pp_expand_function_macro(scc_pp_macro_t *macro,
for (usize j = 0; j < macro->params.size; ++j) {
if (scc_strcmp(
scc_cstring_as_cstr(&scc_vec_at(macro->replaces, i)),
scc_cstring_as_cstr(&scc_vec_at(macro->params, j))) == 0) {
Assert(&scc_vec_at(*params, j) != null);
scc_vec_push(list, scc_cstring_copy(&scc_vec_at(*params, j)));
scc_cstring_as_cstr(&scc_vec_at(macro->params, j))) != 0) {
continue;
}
if (params->size == 0) {
scc_vec_push(list, scc_cstring_from_cstr(""));
goto END;
}
Assert(&scc_vec_at(*params, j) != null);
scc_vec_push(list, scc_cstring_copy(&scc_vec_at(*params, j)));
goto END;
}
scc_vec_push(list, scc_cstring_copy(&scc_vec_at(macro->replaces, i)));
END:;
@@ -110,10 +115,10 @@ typedef struct {
scc_pp_macro_table_t *macros;
scc_pp_macro_table_t painted_blue; // 正在展开的宏
int depth;
} macro_expansion_state_t;
} scc_expansion_ctx_t;
// 进入宏展开
static void enter_macro_expansion(macro_expansion_state_t *state,
static void enter_macro_expansion(scc_expansion_ctx_t *state,
scc_pp_macro_t *macro) {
// 添加到活动宏集合
scc_pp_macro_table_set(&state->painted_blue,
@@ -121,45 +126,152 @@ static void enter_macro_expansion(macro_expansion_state_t *state,
}
// 离开宏展开(开始重新扫描)
static void leave_macro_expansion(macro_expansion_state_t *state,
static void leave_macro_expansion(scc_expansion_ctx_t *state,
scc_pp_macro_t *macro) {
// 从活动宏移除,添加到禁用宏
scc_pp_macro_table_remove(&state->painted_blue, &macro->name);
}
// 检查是否可以展开
static cbool can_expand_macro(macro_expansion_state_t *state,
static cbool can_expand_macro(scc_expansion_ctx_t *state,
scc_pp_macro_t *macro) {
return scc_pp_macro_table_get(&state->painted_blue, &macro->name) == null;
}
static cbool _scc_pp_expand_macro(scc_probe_stream_t *stream,
macro_expansion_state_t *state,
scc_probe_stream_t **out_stream);
typedef struct {
scc_cstring_t identifier;
scc_pp_macro_list_t args;
} scc_expand_unit_t;
static cbool expanded_buffer(const scc_cstring_t *in, scc_cstring_t *out,
macro_expansion_state_t *state) {
scc_probe_stream_t *in_stream = scc_mem_probe_stream_new(
void scc_pp_parse_expand_macro(scc_probe_stream_t *stream, scc_pos_t *pos,
scc_expand_unit_t *unit) {
Assert(stream != null && pos != null && unit != null);
// TODO Assert empty unit
scc_cstring_init(&unit->identifier);
scc_vec_init(unit->args);
cbool ret = scc_lex_parse_identifier(stream, pos, &unit->identifier);
Assert(ret == true);
scc_probe_stream_sync(stream);
do {
if (scc_lex_parse_is_whitespace(scc_probe_stream_peek(stream))) {
scc_lex_parse_skip_whitespace(stream, pos);
}
if (scc_probe_stream_peek(stream) != '(') {
// TODO maybe error
// 因为没能正确表述空值
break;
}
// TODO maybe like f()() => maybe twice expand
ret = scc_pp_parse_macro_arguments(stream, &unit->args);
scc_probe_stream_sync(stream);
Assert(ret == true);
} while (0);
}
static cbool expand_buffer(const scc_cstring_t *in, scc_cstring_t *out,
scc_expansion_ctx_t *state);
static inline void args2str_append(const scc_pp_macro_list_t *args,
scc_cstring_t *out) {
Assert(args != null);
if (args->size != 0) {
scc_cstring_append_ch(out, '(');
for (usize i = 0; i < args->size; ++i) {
scc_cstring_append(out, &scc_vec_at(*args, i));
if (i != args->size - 1) {
scc_cstring_append_ch(out, ',');
scc_cstring_append_ch(out, ' ');
}
}
scc_cstring_append_ch(out, ')');
}
}
static cbool expand_macro(const scc_expand_unit_t *unit, scc_cstring_t *out,
scc_expansion_ctx_t *state) {
scc_pp_macro_t *macro =
scc_pp_macro_table_get(state->macros, &unit->identifier);
if (macro == null) {
scc_cstring_append(out, &unit->identifier);
args2str_append(&unit->args, out);
return true;
}
cbool ret;
if (macro->type == SCC_PP_MACRO_OBJECT) {
if (can_expand_macro(state, macro)) {
ret = scc_pp_expand_object_macro(macro, out);
Assert(ret == true);
args2str_append(&unit->args, out);
} else {
scc_cstring_append(out, &macro->name);
args2str_append(&unit->args, out);
return true;
}
} else if (macro->type == SCC_PP_MACRO_FUNCTION) {
/**
* 1. 参数先展开
* 2. 替换后重扫描
* 3. 蓝色集合中不展开
* 4. #, ## 不展开
* 5. 最后的括号要检查
*/
scc_pp_macro_list_t expanded_params;
scc_vec_init(expanded_params);
// expand params fisrt and recursive
for (usize i = 0; i < unit->args.size; ++i) {
scc_cstring_t param = scc_vec_at(unit->args, i);
scc_cstring_t out = scc_cstring_create();
expand_buffer(&param, &out, state);
scc_vec_push(expanded_params, out);
}
if (can_expand_macro(state, macro)) {
ret = scc_pp_expand_function_macro(macro, &unit->args,
&expanded_params, out);
Assert(ret == true);
} else {
scc_cstring_append(out, &macro->name);
args2str_append(&expanded_params, out);
return true;
}
// TODO memory leak
} else {
UNREACHABLE();
}
// 重新扫描展开结果
scc_cstring_t rescanned = scc_cstring_create();
enter_macro_expansion(state, macro);
expand_buffer(out, &rescanned, state);
leave_macro_expansion(state, macro);
scc_cstring_free(out);
*out = rescanned;
return true;
}
static cbool expand_buffer(const scc_cstring_t *in, scc_cstring_t *out,
scc_expansion_ctx_t *state) {
scc_probe_stream_t *in_stream = scc_mem_probe_stream_alloc(
scc_cstring_as_cstr(in), scc_cstring_len(in), false);
// rescanning
int ch;
scc_pos_t pos;
scc_expand_unit_t unit;
while ((ch = scc_probe_stream_peek(in_stream)) != scc_stream_eof) {
if (scc_lex_parse_is_identifier_prefix(ch)) {
// 递归检查
scc_probe_stream_t *out_stream;
if (_scc_pp_expand_macro(in_stream, state, &out_stream) == false) {
scc_cstring_free(out);
scc_cstring_t expanded_buffer = scc_cstring_create();
scc_pp_parse_expand_macro(in_stream, &pos, &unit);
scc_probe_stream_reset(in_stream);
if (expand_macro(&unit, &expanded_buffer, state) == false) {
scc_cstring_free(&expanded_buffer);
return false;
} else {
scc_cstring_append(out, &expanded_buffer);
scc_cstring_free(&expanded_buffer);
}
Assert(out_stream != null);
while (scc_probe_stream_peek(out_stream) != scc_stream_eof) {
scc_cstring_append_ch(out,
scc_probe_stream_consume(out_stream));
}
Assert(out_stream != null && out_stream->drop != null);
scc_probe_stream_drop(out_stream);
} else {
scc_cstring_append_ch(out, scc_probe_stream_consume(in_stream));
}
@@ -169,128 +281,134 @@ static cbool expanded_buffer(const scc_cstring_t *in, scc_cstring_t *out,
return true;
}
/**
* 1. 参数先展开
* 2. 替换后重扫描
* 3. 蓝色集合中不展开
* 4. #, ## 不展开
* 5. 最后的括号要检查
*/
static cbool _scc_pp_expand_macro(scc_probe_stream_t *stream,
macro_expansion_state_t *state,
scc_probe_stream_t **out_stream) {
// TODO self position and it maybe is a stack on #include ?
// 递归扫描
if (state->depth-- <= 0) {
*out_stream = null;
return false;
}
scc_pp_macro_table_t *macros = state->macros;
scc_cstring_t identifier = scc_cstring_new();
scc_pos_t pos = scc_pos_init();
// static cbool scc_pp_expand_macro_impl(scc_probe_stream_t *stream,
// scc_expansion_ctx_t *ctx, scc_pos_t
// *pos, scc_cstring_t *output) {
// // TODO self position and it maybe is a stack on #include ?
// // 递归扫描
// if (ctx->depth-- <= 0) {
// scc_cstring_free(output);
// return false;
// }
// cbool ret;
// scc_pp_macro_table_t *macros = ctx->macros;
cbool ret;
ret = scc_lex_parse_identifier(stream, &pos, &identifier);
Assert(ret == true);
// scc_cstring_t identifier = scc_cstring_create();
// ret = scc_lex_parse_identifier(stream, pos, &identifier);
// Assert(ret == true);
scc_pp_macro_t *macro = scc_pp_macro_table_get(macros, &identifier);
// scc_pp_macro_t *macro = scc_pp_macro_table_get(macros, &identifier);
// 1. 不是宏,直接输出标识符
if (macro == null) {
// 不是宏,直接输出
usize length = scc_cstring_len(&identifier);
*out_stream = scc_mem_probe_stream_new(
scc_cstring_move_cstr(&identifier), length, true);
return true;
} else {
scc_cstring_free(&identifier);
}
// // 1. 不是宏,直接输出标识符
// if (macro == null) {
// // 不是宏,直接输出
// usize length = scc_cstring_len(&identifier);
// *out_stream = scc_mem_probe_stream_alloc(
// scc_cstring_move_cstr(&identifier), length, true);
// return true;
// } else {
// scc_cstring_free(&identifier);
// }
// 收集参数(如果是函数宏)
scc_pp_macro_list_t params;
scc_vec_init(params);
if (macro->type == SCC_PP_MACRO_FUNCTION) {
// TODO when expand need check another func with () at the end
scc_lex_parse_skip_whitespace(stream, &pos);
if (scc_probe_stream_peek(stream) != '(') {
goto ORIGIN;
}
ret = scc_pp_parse_macro_arguments(stream, &params);
Assert(ret == true);
}
// // 收集参数(如果是函数宏)
// scc_pp_macro_list_t params;
// scc_pp_macro_list_t expanded_params;
// scc_vec_init(params);
// scc_vec_init(expanded_params);
// if (macro->type == SCC_PP_MACRO_FUNCTION) {
// // TODO when expand need check another func with () at the end
// scc_lex_parse_skip_whitespace(stream, &pos);
// if (scc_probe_stream_peek(stream) != '(') {
// goto ORIGIN;
// }
// ret = scc_pp_parse_macro_arguments(stream, &params);
// Assert(ret == true);
// 2. 检查到重复展开跳过
// 检查是否可以展开
if (!can_expand_macro(state, macro)) {
ORIGIN:
// 输出原始调用
scc_cstring_t original = scc_cstring_new();
scc_cstring_append(&original, &macro->name);
if (macro->type == SCC_PP_MACRO_FUNCTION && params.size != 0) {
scc_cstring_append_ch(&original, '(');
for (usize i = 0; i < params.size; ++i) {
scc_cstring_append(&original, &scc_vec_at(params, i));
if (i != params.size - 1) {
scc_cstring_append_ch(&original, ',');
scc_cstring_append_ch(&original, ' ');
}
}
scc_cstring_append_ch(&original, ')');
}
*out_stream = scc_mem_probe_stream_new(
scc_cstring_as_cstr(&original), scc_cstring_len(&original), true);
scc_vec_free(params);
return true;
}
// // expand params fisrt and recursive
// for (usize i = 0; i < params.size; ++i) {
// scc_cstring_t param = scc_vec_at(params, i);
// scc_cstring_t out = scc_cstring_create();
// expand_buffer(&param, &out, ctx);
// scc_vec_push(expanded_params, out);
// }
// }
// 开始展开
scc_cstring_t expanded = scc_cstring_new();
if (macro->type == SCC_PP_MACRO_OBJECT) {
ret = scc_pp_expand_object_macro(macro, &expanded);
Assert(ret == true);
goto RESCANNING;
} else if (macro->type != SCC_PP_MACRO_FUNCTION) {
TODO();
}
// // 2. 检查到重复展开跳过
// // 检查是否可以展开
// if (!can_expand_macro(ctx, macro)) {
// ORIGIN:
// // 输出原始调用
// scc_cstring_t original = scc_cstring_create();
// scc_cstring_append(&original, &macro->name);
// if (macro->type == SCC_PP_MACRO_FUNCTION && expanded_params.size !=
// 0) {
// scc_cstring_append_ch(&original, '(');
// for (usize i = 0; i < expanded_params.size; ++i) {
// scc_cstring_append(&original, &scc_vec_at(expanded_params,
// i)); if (i != expanded_params.size - 1) {
// scc_cstring_append_ch(&original, ',');
// scc_cstring_append_ch(&original, ' ');
// }
// }
// scc_cstring_append_ch(&original, ')');
// }
// *out_stream = scc_mem_probe_stream_alloc(
// scc_cstring_as_cstr(&original), scc_cstring_len(&original),
// true);
// scc_vec_free(params);
// scc_vec_free(expanded_params);
// return true;
// }
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
// // 开始展开
// scc_cstring_t expanded = scc_cstring_create();
// if (macro->type == SCC_PP_MACRO_OBJECT) {
// ret = scc_pp_expand_object_macro(macro, &expanded);
// Assert(ret == true);
// } else if (macro->type == SCC_PP_MACRO_FUNCTION) {
// ret = scc_pp_expand_function_macro(macro, &params, &expanded_params,
// &expanded);
// Assert(ret == true);
// } else {
// UNREACHABLE();
// }
scc_pp_macro_list_t expanded_params;
scc_vec_init(expanded_params);
// expand params fisrt and recursive
for (usize i = 0; i < params.size; ++i) {
scc_cstring_t param = scc_vec_at(params, i);
scc_cstring_t out = scc_cstring_new();
expanded_buffer(&param, &out, state);
scc_vec_push(expanded_params, out);
}
ret = scc_pp_expand_function_macro(macro, &params, &expanded_params,
&expanded);
Assert(ret == true);
// // 重新扫描展开结果
// // 将展开内容变换成stream并递归展开
// scc_cstring_t rescanned = scc_cstring_create();
// enter_macro_expansion(ctx, macro);
// expand_buffer(&expanded, &rescanned, ctx);
// leave_macro_expansion(ctx, macro);
RESCANNING:
// 重新扫描展开结果
// 将展开内容变换成stream并递归展开
scc_cstring_t rescanned = scc_cstring_new();
enter_macro_expansion(state, macro);
expanded_buffer(&expanded, &rescanned, state);
leave_macro_expansion(state, macro);
// scc_cstring_free(&expanded);
// // TODO memory leak
scc_cstring_free(&expanded);
*out_stream = scc_mem_probe_stream_new(scc_cstring_as_cstr(&rescanned),
scc_cstring_len(&rescanned), true);
return true;
}
// *out_stream = scc_mem_probe_stream_alloc(scc_cstring_as_cstr(&rescanned),
// scc_cstring_len(&rescanned),
// true);
// return true;
// }
cbool scc_pp_expand_macro(scc_probe_stream_t *stream,
scc_pp_macro_table_t *macros,
scc_probe_stream_t **out_stream, int depth) {
Assert(depth > 0 && stream != null && macros != null && out_stream != null);
macro_expansion_state_t state;
scc_expansion_ctx_t state;
state.depth = depth;
scc_pp_marco_table_init(&state.painted_blue);
state.macros = macros;
cbool ret = _scc_pp_expand_macro(stream, &state, out_stream);
scc_cstring_t buffer = scc_cstring_create();
scc_pos_t pos;
// cbool ret = scc_pp_expand_macro_impl(stream, &state, &pos, &buffer);
// expand_buffer(stream, &buffer, &state);
scc_expand_unit_t unit;
scc_pp_parse_expand_macro(stream, &pos, &unit);
scc_probe_stream_reset(stream);
expand_macro(&unit, &buffer, &state);
*out_stream = scc_mem_probe_stream_alloc(scc_cstring_as_cstr(&buffer),
scc_cstring_len(&buffer), true);
scc_pp_macro_table_drop(&state.painted_blue);
return ret;
return true;
}

View File

@@ -100,7 +100,7 @@ scc_pp_macro_t *scc_pp_macro_table_set(scc_pp_macro_table_t *pp,
// 查找宏定义
scc_pp_macro_t *scc_pp_macro_table_get(scc_pp_macro_table_t *pp,
scc_cstring_t *name) {
const scc_cstring_t *name) {
return scc_hashtable_get(&pp->table, name);
}

View File

@@ -51,19 +51,19 @@ static inline void try_to_cut_list(scc_pp_macro_list_t *list,
scc_cstring_t *buff) {
if (scc_cstring_len(buff) != 0) {
scc_vec_push(*list, *buff);
*buff = scc_cstring_new();
*buff = scc_cstring_create();
}
}
cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream,
scc_pp_macro_list_t *list) {
Assert(stream != null && list != null);
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
scc_vec_init(*list);
scc_cstring_t replacement = scc_cstring_new();
scc_cstring_t replacement = scc_cstring_create();
int ch;
scc_pos_t pos = scc_pos_init();
scc_pos_t pos = scc_pos_create();
while ((ch = scc_probe_stream_peek(stream)) != scc_stream_eof) {
if (scc_lex_parse_is_endline(ch)) {
@@ -76,13 +76,13 @@ cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream,
try_to_cut_list(list, &replacement);
} else if (ch == '#') {
// 处理 # 和 ## 操作符
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
try_to_cut_list(list, &replacement);
scc_cstring_append_ch(&replacement, '#');
if (scc_probe_stream_peek(stream) == '#') {
// ## 连接操作符
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
scc_cstring_append_ch(&replacement, '#');
}
// 我需要尽可能防止空白字符干扰解析
@@ -94,14 +94,14 @@ cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream,
scc_cstring_append_ch(&replacement, ' ');
try_to_cut_list(list, &replacement);
} else {
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
scc_cstring_append_ch(&replacement, (char)ch);
}
}
if (scc_cstring_len(&replacement) != 0) {
scc_vec_push(*list, replacement);
replacement = scc_cstring_new();
replacement = scc_cstring_create();
}
// for (usize i = 0; i < list->size; ++i) {
@@ -118,18 +118,18 @@ cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream,
scc_vec_init(*args);
int ch;
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
// 跳过 '('
ch = scc_probe_stream_peek(stream);
if (ch != '(') {
return false;
}
scc_probe_stream_consume(stream); // 消费 '('
scc_probe_stream_next(stream); // 消费 '('
int paren_depth = 1;
scc_cstring_t current_arg = scc_cstring_new();
scc_pos_t pos = scc_pos_init();
scc_cstring_t current_arg = scc_cstring_create();
scc_pos_t pos = scc_pos_create();
while (paren_depth > 0) {
ch = scc_probe_stream_peek(stream);
@@ -142,23 +142,23 @@ cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream,
if (ch == '(') {
paren_depth++;
scc_cstring_append_ch(&current_arg, (char)ch);
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
} else if (ch == ')') {
paren_depth--;
if (paren_depth > 0) {
scc_cstring_append_ch(&current_arg, (char)ch);
}
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
} else if (ch == ',' && paren_depth == 1) {
// 参数分隔符
scc_vec_push(*args, current_arg);
current_arg = scc_cstring_new();
scc_probe_stream_consume(stream);
current_arg = scc_cstring_create();
scc_probe_stream_next(stream);
// 跳过参数后的空白
scc_lex_parse_skip_whitespace(stream, &pos);
} else {
scc_cstring_append_ch(&current_arg, (char)ch);
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
}
}
@@ -175,7 +175,7 @@ cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream,
static cbool safe_skip_backspace_if_endline(scc_probe_stream_t *stream,
scc_pos_t *pos) {
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
int ch = scc_probe_stream_peek(stream);
// FIXME maybe it not correct
while (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') {
@@ -183,10 +183,10 @@ static cbool safe_skip_backspace_if_endline(scc_probe_stream_t *stream,
scc_lex_parse_skip_endline(stream, pos);
return true;
}
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
ch = scc_probe_stream_peek(stream);
}
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
return false;
}
@@ -194,19 +194,19 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos,
scc_pp_macro_table_t *macros) {
Assert(stream != null);
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
// 跳过 '#' 和后续空白
if (scc_probe_stream_peek(stream) != '#') {
LOG_WARN("Invalid directive");
return;
}
scc_pos_next(pos);
scc_probe_stream_consume(stream);
scc_probe_stream_next(stream);
if (safe_skip_backspace_if_endline(stream, pos))
return;
// 解析指令名称
scc_cstring_t directive = scc_cstring_new();
scc_cstring_t directive = scc_cstring_create();
if (!scc_lex_parse_identifier(stream, pos, &directive)) {
goto ERR;
}
@@ -216,16 +216,15 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos,
scc_pp_token_t token = keyword_cmp(scc_cstring_as_cstr(&directive),
scc_cstring_len(&directive));
scc_cstring_t name = scc_cstring_new();
scc_cstring_t name = scc_cstring_create();
switch (token) {
case SCC_PP_TOK_DEFINE: {
if (!scc_lex_parse_identifier(stream, pos, &name)) {
scc_cstring_free(&name);
goto ERR;
}
// 检查是否是函数宏:宏名后是否直接跟着 '('(没有空白字符)
scc_probe_stream_reset(stream);
// scc_probe_stream_reset(stream);
int ch = scc_probe_stream_peek(stream);
cbool has_whitespace = scc_lex_parse_is_whitespace(ch);
if (has_whitespace && safe_skip_backspace_if_endline(stream, pos)) {
@@ -241,7 +240,7 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos,
ch = scc_probe_stream_peek(stream);
if (ch == ')') {
scc_probe_stream_consume(stream); // 消费 ')'
scc_probe_stream_next(stream); // 消费 ')'
}
if (safe_skip_backspace_if_endline(stream, pos)) {
goto FREE;
@@ -256,13 +255,12 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos,
scc_pp_parse_macro_replace_list(stream, &replacement);
scc_pp_add_object_macro(macros, &name, &replacement);
}
scc_cstring_free(&name);
break;
}
case SCC_PP_TOK_UNDEF: {
if (scc_lex_parse_identifier(stream, pos, &name)) {
// TODO ret value
scc_pp_macro_table_remove(macros, &name);
cbool ret = scc_pp_macro_table_remove(macros, &name);
Assert(ret == true);
}
break;
}
@@ -279,9 +277,10 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos,
case SCC_PP_TOK_EMBED:
case SCC_PP_TOK_ERROR:
case SCC_PP_TOK_WARNING:
case SCC_PP_TOK_PRAMA:
case SCC_PP_TOK_PRAGMA:
// 暂时跳过这一行
scc_lex_parse_skip_line(stream, pos);
TODO();
break;
default:
LOG_WARN("Unknown preprocessor directive: %s",

View File

@@ -32,6 +32,7 @@ RETRY:
if (ch == '#') {
scc_pp_parse_directive(stream->input, &stream->pos,
&stream->self->macro_table);
scc_probe_stream_sync(stream->input);
goto RETRY;
} else if (scc_lex_parse_is_identifier_prefix(ch)) {
cbool ret =
@@ -44,9 +45,13 @@ RETRY:
} else if (scc_probe_stream_next(stream->input) == '/') {
ch = scc_probe_stream_peek(stream->input);
if (ch == '/') {
scc_probe_stream_reset(stream->input);
scc_lex_parse_skip_line(stream->input, &stream->pos);
scc_probe_stream_sync(stream->input);
} else if (ch == '*') {
scc_probe_stream_reset(stream->input);
scc_lex_parse_skip_block_comment(stream->input, &stream->pos);
scc_probe_stream_sync(stream->input);
}
}
@@ -81,7 +86,7 @@ static scc_probe_stream_t *pp_stream_init(scc_pproc_t *self,
stream->input = input;
stream->tmp_stream = null;
stream->pos = scc_pos_init();
stream->pos = scc_pos_create();
stream->stream.name = scc_cstring_from_cstr("pp_stream");
stream->stream.consume = pp_stream_read_char;

View File

@@ -15,7 +15,7 @@ static cbool process_input(const char *input, scc_cstring_t *output) {
// 获取输出结果
int ch;
*output = scc_cstring_new();
*output = scc_cstring_create();
while (1) {
ch = scc_probe_stream_consume(output_stream);
if (ch == scc_stream_eof) {
@@ -104,6 +104,17 @@ static void test_define_nested_macros(void) {
"((1 + 1) + 1)\n");
}
static void test_undef_macros(void) {
TEST_CASE("test_undef_macros");
CHECK_PP_OUTPUT_EXACT("#define x 1\n"
"x\n"
"#undef x\n"
"x\n"
"#define x 2\n"
"x\n",
"1\nx\n2\n");
}
static void hard_test_define_func_macros(void) {
TEST_CASE("func_macros_hard with pp_01");
CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n"
@@ -139,6 +150,27 @@ static void hard_test_define_func_macros(void) {
"#define M3(x) x\n"
"M3(M3(M2)(0))\n",
"M1(0 + 1)\n");
TEST_CASE("TODO");
CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n"
"str()\n",
"\"\"\n");
TEST_CASE("TODO");
CHECK_PP_OUTPUT_EXACT("#define x 1\n"
"#define f(a) f(x * (a))\n"
"f(0)\n"
"f(x)",
"f(1 * (0))\n"
"f(1 * (1))");
CHECK_PP_OUTPUT_EXACT("#define x x(0)\n"
"#define f(a) f(x * (a))\n"
"f(f(0))\n"
"f(f(x))\n"
"f(f(a))\n",
"f(x(0) * (f(x(0) * (0))))\n"
"f(x(0) * (f(x(0) * (x(0)))))\n"
"f(x(0) * (f(x(0) * (a))))\n");
}
static void test_conditional_compilation(void) {
@@ -177,6 +209,7 @@ TEST_LIST = {
TEST_LIST_CASE(test_define_stringify_operator),
TEST_LIST_CASE(test_define_concat_operator),
TEST_LIST_CASE(test_define_nested_macros),
TEST_LIST_CASE(test_undef_macros),
TEST_LIST_CASE(hard_test_define_func_macros),
{NULL, NULL},
};