Files
scc/libs/pprocessor/tests/test_unit.c
zzy e6a76e7a86 feat(lex_parser): 提取字符判断函数并增强解析器断言
将 `is_next_line` 内联函数重命名为 `lex_parse_is_endline` 并新增 `lex_parse_is_whitespace` 函数,统一用于词法解析中的字符分类。同时加强多个解析函数的输入参数断言,提升代码健壮性。

此外,修正了 `lex_parse_skip_whitespace` 中的逻辑错误,并优化部分注释和控制流结构。

feat(pprocessor): 初始化预处理器模块并添加基础功能实现

新增预处理器模块 `pprocessor`,包括宏定义、条件编译状态管理以及基本的指令解析框架。实现了标识符解析、空白跳过、关键字查找等功能,并初步支持 `#define` 指令的对象类宏替换。

该提交还引入了一组测试用例,覆盖多种宏展开场景及边界情况,确保预处理器的核心行为符合预期。
2025-11-24 22:44:08 +08:00

101 lines
3.8 KiB
C

#include <assert.h>
#include <pprocessor.h>
#include <string.h>
#include <utest/acutest.h>
static cbool process_input(const char *input, cstring_t *output) {
smcc_pp_t pp;
core_mem_stream_t mem_stream;
core_stream_t *output_stream;
// 初始化预处理器
output_stream = pp_init(
&pp, core_mem_stream_init(&mem_stream, input, strlen(input), false));
// 获取输出结果
int ch;
*output = cstring_new();
while (1) {
ch = core_stream_next_char(output_stream);
if (ch == core_stream_eof) {
break;
}
cstring_push(output, (char)ch);
}
// 清理资源
pp_drop(&pp);
return true;
}
#define CHECK_PP_OUTPUT_EXACT(input, expect) \
do { \
cstring_t output; \
process_input(input, &output); \
assert(output.data != NULL); \
TEST_CHECK(strcmp(output.data, expect) == 0); \
} while (0)
#define CHECK_PP_OUTPUT_CONTAIN(input, expect) \
do { \
cstring_t output; \
process_input(input, &output); \
assert(output.data != NULL); \
TEST_CHECK(strstr(output.data, expect) != NULL); \
} while (0)
static void test_define_simple_object_macro(void) {
TEST_CASE("simple object-like macro");
CHECK_PP_OUTPUT_EXACT("#define MAX 100\nMAX\n", "100\n");
CHECK_PP_OUTPUT_EXACT("#define NAME test\r\nNAME\n", "test\n");
}
static void test_define_complex_object_macro(void) {
TEST_CASE("complex object-like macro");
CHECK_PP_OUTPUT_EXACT("#define VALUE (100 + 50)\nVALUE\n", "(100 + 50)\n");
CHECK_PP_OUTPUT_EXACT("#define PI 3.14159\nPI\n", "3.14159\n");
}
static void test_define_function_macro(void) {
TEST_CASE("function-like macro");
CHECK_PP_OUTPUT_EXACT("#define ADD(a,b) a + b\nADD(1, 2)\n", "1 + 2\n");
CHECK_PP_OUTPUT_EXACT(
"#define MAX(a,b) ((a) > (b) ? (a) : (b))\nMAX(10, 20)\n",
"((10) > (20) ? (10) : (20))\n");
}
static void test_define_stringify_operator(void) {
TEST_CASE("stringify operator (#)");
CHECK_PP_OUTPUT_EXACT("#define STRINGIFY(x) #x\nSTRINGIFY(hello)\n",
"\"hello\"\n");
CHECK_PP_OUTPUT_EXACT("#define STR(x) #x\nSTR(test value)\n",
"\"test value\"\n");
}
static void test_define_concat_operator(void) {
TEST_CASE("concatenation operator (##)");
CHECK_PP_OUTPUT_EXACT("#define CONCAT(a,b) a##b\nCONCAT(hello,world)\n",
"helloworld\n");
CHECK_PP_OUTPUT_EXACT("#define JOIN(pre,suf) pre##suf\nJOIN(var,123)\n",
"var123\n");
}
static void test_define_nested_macros(void) {
TEST_CASE("nested macros");
CHECK_PP_OUTPUT_EXACT(
"#define MAX 100\n#define TWICE_MAX (MAX * 2)\nTWICE_MAX\n",
"(100 * 2)\n");
CHECK_PP_OUTPUT_EXACT(
"#define A 1\n#define B (A + 1)\n#define C (B + 1)\nC\n",
"((1 + 1) + 1)\n");
}
TEST_LIST = {
{"test_define_simple_object_macro", test_define_simple_object_macro},
{"test_define_complex_object_macro", test_define_complex_object_macro},
{"test_define_function_macro", test_define_function_macro},
{"test_define_stringify_operator", test_define_stringify_operator},
{"test_define_concat_operator", test_define_concat_operator},
{"test_define_nested_macros", test_define_nested_macros},
{NULL, NULL},
};