From 09f4ac8de061d5310bbd970fb11e06d2371c2a4f Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sun, 28 Dec 2025 10:49:29 +0800 Subject: [PATCH] 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 --- libs/lex_parser/src/lex_parser.c | 73 ++-- libs/lex_parser/tests/test_char.c | 8 +- libs/lex_parser/tests/test_identifier.c | 6 +- libs/lex_parser/tests/test_number.c | 2 +- .../tests/test_skip_block_comment.c | 3 +- libs/lex_parser/tests/test_skip_line.c | 3 +- libs/lex_parser/tests/test_string.c | 6 +- libs/lexer/src/lexer.c | 47 ++- libs/lexer/tests/test_run.c | 3 +- libs/pprocessor/include/pp_macro.h | 3 +- libs/pprocessor/include/pp_token.h | 32 +- libs/pprocessor/src/expand_macro.c | 392 ++++++++++++------ libs/pprocessor/src/macro.c | 2 +- libs/pprocessor/src/parse.c | 61 ++- libs/pprocessor/src/pprocessor.c | 7 +- libs/pprocessor/tests/test_unit.c | 35 +- runtime/libcore/include/core_pos.h | 4 +- runtime/libcore/include/core_str.h | 12 +- runtime/libcore/include/core_stream.h | 4 +- runtime/libcore/src/stream.c | 4 +- 20 files changed, 445 insertions(+), 262 deletions(-) diff --git a/libs/lex_parser/src/lex_parser.c b/libs/lex_parser/src/lex_parser.c index 09f2c2c..9a985a0 100644 --- a/libs/lex_parser/src/lex_parser.c +++ b/libs/lex_parser/src/lex_parser.c @@ -2,17 +2,17 @@ void scc_lex_parse_skip_endline(scc_probe_stream_t *input, scc_pos_t *pos) { Assert(input != null && pos != null); - scc_probe_stream_reset(input); + // scc_probe_stream_reset(input); int ch = scc_probe_stream_peek(input); if (ch == '\r') { - scc_probe_stream_consume(input); + scc_probe_stream_next(input); ch = scc_probe_stream_peek(input); if (ch == '\n') { - scc_probe_stream_consume(input); + scc_probe_stream_next(input); } scc_pos_next_line(pos); } else if (ch == '\n') { - scc_probe_stream_consume(input); + scc_probe_stream_next(input); scc_pos_next_line(pos); } else { LOG_WARN("not a newline character"); @@ -60,7 +60,7 @@ static inline int got_simple_escape(int ch) { void scc_lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos) { scc_probe_stream_t *stream = input; Assert(stream != null && pos != null); - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); while (1) { int ch = scc_probe_stream_peek(stream); @@ -73,7 +73,7 @@ void scc_lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos) { scc_lex_parse_skip_endline(stream, pos); return; } else { - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); } } @@ -84,18 +84,18 @@ void scc_lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_probe_stream_t *stream = input; Assert(stream != null && pos != null); int ch; - scc_probe_stream_reset(stream); - ch = scc_probe_stream_consume(stream); + // scc_probe_stream_reset(stream); + ch = scc_probe_stream_next(stream); scc_pos_next(pos); // FIXME Assertion Assert(ch == '/'); - ch = scc_probe_stream_consume(stream); + ch = scc_probe_stream_next(stream); scc_pos_next(pos); Assert(ch == '*'); // all ready match `/*` while (1) { - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); ch = scc_probe_stream_peek(stream); if (ch == scc_stream_eof) { @@ -107,12 +107,12 @@ void scc_lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_lex_parse_skip_endline(stream, pos); continue; } - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); if (ch == '*') { ch = scc_probe_stream_peek(stream); if (ch == '/') { - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); return; } @@ -123,7 +123,7 @@ void scc_lex_parse_skip_block_comment(scc_probe_stream_t *input, void scc_lex_parse_skip_whitespace(scc_probe_stream_t *input, scc_pos_t *pos) { scc_probe_stream_t *stream = input; Assert(stream != null && pos != null); - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); while (1) { int ch = scc_probe_stream_peek(stream); @@ -131,7 +131,7 @@ void scc_lex_parse_skip_whitespace(scc_probe_stream_t *input, scc_pos_t *pos) { return; } - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); } } @@ -143,7 +143,7 @@ static inline cbool _lex_parse_uint(scc_probe_stream_t *input, scc_pos_t *pos, return false; } Assert(base == 2 || base == 8 || base == 10 || base == 16); - scc_probe_stream_reset(input); + // scc_probe_stream_reset(input); int ch, tmp; usize n = 0; usize offset = pos->offset; @@ -167,7 +167,7 @@ static inline cbool _lex_parse_uint(scc_probe_stream_t *input, scc_pos_t *pos, return false; } - scc_probe_stream_consume(input); + scc_probe_stream_next(input); scc_pos_next(pos); n = n * base + tmp; // TODO number overflow @@ -191,8 +191,8 @@ static inline cbool _lex_parse_uint(scc_probe_stream_t *input, scc_pos_t *pos, int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) { scc_probe_stream_t *stream = input; Assert(stream != null && pos != null); - scc_probe_stream_reset(stream); - int ch = scc_probe_stream_peek(stream); + int ch = scc_probe_stream_next(stream); + scc_pos_next(pos); int ret = scc_stream_eof; if (ch == scc_stream_eof) { @@ -202,17 +202,16 @@ int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) { LOG_WARN("Unexpected character '%c' at begin", ch); goto ERR; } - scc_probe_stream_consume(stream); - scc_pos_next(pos); + // scc_probe_stream_next(stream); - ch = scc_probe_stream_consume(stream); + ch = scc_probe_stream_next(stream); scc_pos_next(pos); if (ch == scc_stream_eof) { LOG_WARN("Unexpected EOF at middle"); goto ERR; } else if (ch == '\\') { - ch = scc_probe_stream_consume(stream); + ch = scc_probe_stream_next(stream); scc_pos_next(pos); if (ch == '0') { // 数字转义序列 @@ -238,7 +237,7 @@ int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) { } else { ret = ch; } - if ((ch = scc_probe_stream_consume(stream)) != '\'') { + if ((ch = scc_probe_stream_next(stream)) != '\'') { LOG_ERROR("Unclosed character literal '%c' at end, expect `'`", ch); scc_pos_next(pos); goto ERR; @@ -262,7 +261,7 @@ cbool scc_lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos, scc_cstring_t *output) { scc_probe_stream_t *stream = input; Assert(stream != null && pos != null && output != null); - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); int ch = scc_probe_stream_peek(stream); Assert(scc_cstring_is_empty(output)); @@ -273,7 +272,7 @@ cbool scc_lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos, LOG_WARN("Unexpected character '%c' at begin", ch); goto ERR; } - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); scc_cstring_t str = scc_cstring_from_cstr(""); @@ -288,8 +287,8 @@ cbool scc_lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos, goto ERR; } else if (ch == '\\') { // TODO bad practice and maybe bugs here - scc_probe_stream_consume(stream); - ch = scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); + ch = scc_probe_stream_next(stream); int val = got_simple_escape(ch); if (val == -1) { LOG_ERROR("Invalid escape character it is \\%c [%d]", ch, ch); @@ -298,12 +297,12 @@ cbool scc_lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos, continue; } } else if (ch == '"') { - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); break; } - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); scc_cstring_append_ch(&str, ch); } @@ -328,7 +327,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos, usize *output) { scc_probe_stream_t *stream = input; Assert(stream != null && pos != null && output != null); - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); int ch = scc_probe_stream_peek(stream); int base = 10; // 默认十进制 @@ -339,7 +338,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos, if (ch == '0') { // 消费 '0' - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); // 查看下一个字符 @@ -347,12 +346,12 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos, if (ch == 'x' || ch == 'X') { // 十六进制 base = 16; - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); } else if (ch == 'b' || ch == 'B') { // 二进制 (C23扩展) base = 2; - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); } else if (ch >= '0' && ch <= '7') { // 八进制 @@ -375,7 +374,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos, } // 解析整数部分 - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); usize n; if (_lex_parse_uint(stream, pos, base, &n) == false) { // 如果没有匹配任何数字,但输入是 '0',已经处理过了 @@ -384,7 +383,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos, // 单个数字的情况,例如 "1" // 我们需要消费这个数字并返回它的值 if (ch >= '1' && ch <= '9') { - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); *output = ch - '0'; return true; @@ -412,7 +411,7 @@ cbool scc_lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos, Assert(input != null && pos != null && output != null); Assert(scc_cstring_is_empty(output)); scc_probe_stream_t *stream = input; - scc_probe_stream_reset(stream); + // scc_probe_stream_reset(stream); int ch = scc_probe_stream_peek(stream); if (ch == scc_stream_eof) { @@ -420,7 +419,7 @@ cbool scc_lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos, } else if (scc_lex_parse_is_identifier_prefix(ch)) { while (1) { scc_cstring_append_ch(output, ch); - scc_probe_stream_consume(stream); + scc_probe_stream_next(stream); scc_pos_next(pos); ch = scc_probe_stream_peek(stream); if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || diff --git a/libs/lex_parser/tests/test_char.c b/libs/lex_parser/tests/test_char.c index a42d2b4..f7fde2e 100644 --- a/libs/lex_parser/tests/test_char.c +++ b/libs/lex_parser/tests/test_char.c @@ -4,12 +4,16 @@ cbool check_char(const char *str, int expect, int *output) { log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); *output = scc_lex_parse_char(stream, &pos); - return *output == expect; + cbool ret1 = *output == expect; + scc_probe_stream_reset(stream); + *output = scc_lex_parse_char(stream, &pos); + cbool ret2 = *output == expect; + return ret1 && ret2; } #define CHECK_CHAR_VALID(str, expect) \ diff --git a/libs/lex_parser/tests/test_identifier.c b/libs/lex_parser/tests/test_identifier.c index 429c4a6..c7c77e4 100644 --- a/libs/lex_parser/tests/test_identifier.c +++ b/libs/lex_parser/tests/test_identifier.c @@ -5,7 +5,7 @@ cbool check_identifier(const char *str, const char *expect, scc_cstring_t *output) { log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); @@ -19,7 +19,7 @@ cbool check_identifier(const char *str, const char *expect, #define CHECK_IDENTIFIER_VALID(str, expect) \ do { \ - scc_cstring_t _output = scc_cstring_new(); \ + scc_cstring_t _output = scc_cstring_create(); \ cbool ret = check_identifier(str, expect, &_output); \ TEST_CHECK(ret == true); \ TEST_CHECK(strcmp(_output.data, expect) == 0); \ @@ -28,7 +28,7 @@ cbool check_identifier(const char *str, const char *expect, #define CHECK_IDENTIFIER_INVALID(str) \ do { \ - scc_cstring_t _output = scc_cstring_new(); \ + scc_cstring_t _output = scc_cstring_create(); \ cbool ret = check_identifier(str, NULL, &_output); \ TEST_CHECK(ret == false); \ scc_cstring_free(&_output); \ diff --git a/libs/lex_parser/tests/test_number.c b/libs/lex_parser/tests/test_number.c index 48fd382..9bd6404 100644 --- a/libs/lex_parser/tests/test_number.c +++ b/libs/lex_parser/tests/test_number.c @@ -5,7 +5,7 @@ cbool check(const char *str, usize expect, usize *output) { // TODO maybe have other logger (void)(expect); log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); diff --git a/libs/lex_parser/tests/test_skip_block_comment.c b/libs/lex_parser/tests/test_skip_block_comment.c index 3c33257..9bfc9ae 100644 --- a/libs/lex_parser/tests/test_skip_block_comment.c +++ b/libs/lex_parser/tests/test_skip_block_comment.c @@ -4,12 +4,13 @@ void check_skip_block_comment(const char *str, const char *expect_remaining) { log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); scc_lex_parse_skip_block_comment(stream, &pos); + scc_probe_stream_sync(stream); // Check remaining content char buffer[256] = {0}; diff --git a/libs/lex_parser/tests/test_skip_line.c b/libs/lex_parser/tests/test_skip_line.c index d651c92..f82f0a2 100644 --- a/libs/lex_parser/tests/test_skip_line.c +++ b/libs/lex_parser/tests/test_skip_line.c @@ -4,12 +4,13 @@ void check_skip_line(const char *str, const char *expect_remaining) { log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); scc_lex_parse_skip_line(stream, &pos); + scc_probe_stream_sync(stream); // Check remaining content char buffer[256] = {0}; diff --git a/libs/lex_parser/tests/test_string.c b/libs/lex_parser/tests/test_string.c index dfbd275..f7640e6 100644 --- a/libs/lex_parser/tests/test_string.c +++ b/libs/lex_parser/tests/test_string.c @@ -4,7 +4,7 @@ cbool check_string(const char *str, const char *expect, scc_cstring_t *output) { log_set_level(&__default_logger_root, 0); - scc_pos_t pos = scc_pos_init(); + scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); @@ -18,7 +18,7 @@ cbool check_string(const char *str, const char *expect, scc_cstring_t *output) { #define CHECK_STRING_VALID(str, expect) \ do { \ - scc_cstring_t _output = scc_cstring_new(); \ + scc_cstring_t _output = scc_cstring_create(); \ cbool ret = check_string(str, expect, &_output); \ TEST_CHECK(ret == true); \ TEST_CHECK(strcmp(_output.data, expect) == 0); \ @@ -27,7 +27,7 @@ cbool check_string(const char *str, const char *expect, scc_cstring_t *output) { #define CHECK_STRING_INVALID(str) \ do { \ - scc_cstring_t _output = scc_cstring_new(); \ + scc_cstring_t _output = scc_cstring_create(); \ cbool ret = check_string(str, NULL, &_output); \ TEST_CHECK(ret == false); \ scc_cstring_free(&_output); \ diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index b10f98f..4be17e0 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -77,7 +77,7 @@ static inline int keyword_cmp(const char *name, int len) { void scc_lexer_init(scc_lexer_t *lexer, scc_probe_stream_t *stream) { lexer->stream = stream; - lexer->pos = scc_pos_init(); + lexer->pos = scc_pos_create(); // FIXME lexer->pos.name = scc_cstring_copy(&stream->name); } @@ -91,7 +91,7 @@ static void parse_line(scc_lexer_t *lexer, scc_lexer_tok_t *token) { int ch = scc_probe_stream_next(stream); usize n; - scc_cstring_t str = scc_cstring_new(); + scc_cstring_t str = scc_cstring_create(); if (ch == scc_stream_eof) { LEX_WARN("Unexpected EOF at begin"); @@ -113,13 +113,13 @@ static void parse_line(scc_lexer_t *lexer, scc_lexer_tok_t *token) { } } - if (scc_lex_parse_number(lexer->stream, &lexer->pos, &n) == false) { + if (scc_lex_parse_number(stream, &lexer->pos, &n) == false) { LEX_ERROR("Invalid line number"); goto SKIP_LINE; } if (scc_probe_stream_consume(stream) != ' ') { - scc_lex_parse_skip_line(lexer->stream, &lexer->pos); + scc_lex_parse_skip_line(stream, &lexer->pos); token->loc.line = token->value.n; } @@ -127,19 +127,21 @@ static void parse_line(scc_lexer_t *lexer, scc_lexer_tok_t *token) { LEX_ERROR("Invalid `#` line"); goto SKIP_LINE; } - if (scc_lex_parse_string(lexer->stream, &lexer->pos, &str) == false) { + if (scc_lex_parse_string(stream, &lexer->pos, &str) == false) { LEX_ERROR("Invalid filename"); goto SKIP_LINE; } - scc_lex_parse_skip_line(lexer->stream, &lexer->pos); + scc_lex_parse_skip_line(stream, &lexer->pos); + scc_probe_stream_sync(stream); token->loc.line = n; // FIXME memory leak token->loc.name = scc_cstring_copy(&str); scc_cstring_free(&str); return; SKIP_LINE: - scc_lex_parse_skip_line(lexer->stream, &lexer->pos); + scc_lex_parse_skip_line(stream, &lexer->pos); + scc_probe_stream_sync(stream); ERR: set_err_token(token); scc_cstring_free(&str); @@ -212,11 +214,15 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { type = SCC_TOK_ASSIGN_DIV; goto double_char; case '/': - scc_lex_parse_skip_line(lexer->stream, &lexer->pos); + scc_probe_stream_reset(stream); + scc_lex_parse_skip_line(stream, &lexer->pos); + scc_probe_stream_sync(stream); token->type = SCC_TOK_LINE_COMMENT; goto END; case '*': - scc_lex_parse_skip_block_comment(lexer->stream, &lexer->pos); + scc_probe_stream_reset(stream); + scc_lex_parse_skip_block_comment(stream, &lexer->pos); + scc_probe_stream_sync(stream); token->type = SCC_TOK_BLOCK_COMMENT; goto END; default: @@ -369,7 +375,8 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { break; case '\r': case '\n': - scc_lex_parse_skip_endline(lexer->stream, &lexer->pos); + scc_lex_parse_skip_endline(stream, &lexer->pos); + scc_probe_stream_sync(stream); token->type = SCC_TOK_BLANK; goto END; case '#': @@ -384,7 +391,9 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { case '\'': { token->loc = lexer->pos; token->type = SCC_TOK_CHAR_LITERAL; - int ch = scc_lex_parse_char(lexer->stream, &lexer->pos); + scc_probe_stream_reset(stream); + int ch = scc_lex_parse_char(stream, &lexer->pos); + scc_probe_stream_sync(stream); if (ch == scc_stream_eof) { LEX_ERROR("Unexpected character literal"); token->type = SCC_TOK_UNKNOWN; @@ -396,8 +405,10 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { case '"': { token->loc = lexer->pos; token->type = SCC_TOK_STRING_LITERAL; - scc_cstring_t output = scc_cstring_new(); - if (scc_lex_parse_string(lexer->stream, &lexer->pos, &output) == true) { + scc_cstring_t output = scc_cstring_create(); + scc_probe_stream_reset(stream); + if (scc_lex_parse_string(stream, &lexer->pos, &output) == true) { + scc_probe_stream_sync(stream); token->value.cstr.data = scc_cstring_as_cstr(&output); token->value.cstr.len = scc_cstring_len(&output); } else { @@ -414,7 +425,9 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { token->loc = lexer->pos; token->type = SCC_TOK_INT_LITERAL; usize output; - if (scc_lex_parse_number(lexer->stream, &lexer->pos, &output) == true) { + scc_probe_stream_reset(stream); + if (scc_lex_parse_number(stream, &lexer->pos, &output) == true) { + scc_probe_stream_sync(stream); token->value.n = output; } else { LEX_ERROR("Unexpected number literal"); @@ -431,8 +444,10 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': /* clang-format on */ - scc_cstring_t str = scc_cstring_new(); - cbool ret = scc_lex_parse_identifier(lexer->stream, &lexer->pos, &str); + scc_cstring_t str = scc_cstring_create(); + scc_probe_stream_reset(stream); + cbool ret = scc_lex_parse_identifier(stream, &lexer->pos, &str); + scc_probe_stream_sync(stream); Assert(ret == true); int res = keyword_cmp(scc_cstring_as_cstr(&str), scc_cstring_len(&str)); diff --git a/libs/lexer/tests/test_run.c b/libs/lexer/tests/test_run.c index dddb758..f8c8b08 100644 --- a/libs/lexer/tests/test_run.c +++ b/libs/lexer/tests/test_run.c @@ -28,7 +28,8 @@ int main(int argc, char *argv[]) { } else { // FIXME it is a hack lexer_logger log_set_level(&__smcc_lexer_log, LOG_LEVEL_NOTSET); - log_set_level(NULL, LOG_LEVEL_INFO | LOG_LEVEL_WARN | LOG_LEVEL_ERROR); + log_set_level(NULL, LOG_LEVEL_INFO | LOG_LEVEL_WARN | LOG_LEVEL_ERROR | + LOG_LEVEL_FATAL); } const char *file_name = __FILE__; diff --git a/libs/pprocessor/include/pp_macro.h b/libs/pprocessor/include/pp_macro.h index bdd4bd9..c119aea 100644 --- a/libs/pprocessor/include/pp_macro.h +++ b/libs/pprocessor/include/pp_macro.h @@ -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 从预处理器中删除宏 diff --git a/libs/pprocessor/include/pp_token.h b/libs/pprocessor/include/pp_token.h index 21316b1..eb46c08 100644 --- a/libs/pprocessor/include/pp_token.h +++ b/libs/pprocessor/include/pp_token.h @@ -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 */ diff --git a/libs/pprocessor/src/expand_macro.c b/libs/pprocessor/src/expand_macro.c index 5994306..682453d 100644 --- a/libs/pprocessor/src/expand_macro.c +++ b/libs/pprocessor/src/expand_macro.c @@ -4,7 +4,7 @@ #include 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, ¯o->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, ¯o->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, ¯o->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(¶m, &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, ¯o->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, ¶ms); - 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, ¶ms); +// Assert(ret == true); - // 2. 检查到重复展开跳过 - // 检查是否可以展开 - if (!can_expand_macro(state, macro)) { - ORIGIN: - // 输出原始调用 - scc_cstring_t original = scc_cstring_new(); - scc_cstring_append(&original, ¯o->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(¶m, &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, ¯o->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, ¶ms, &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(¶m, &out, state); - scc_vec_push(expanded_params, out); - } - ret = scc_pp_expand_function_macro(macro, ¶ms, &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; } diff --git a/libs/pprocessor/src/macro.c b/libs/pprocessor/src/macro.c index 8939709..d3d8a62 100644 --- a/libs/pprocessor/src/macro.c +++ b/libs/pprocessor/src/macro.c @@ -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); } diff --git a/libs/pprocessor/src/parse.c b/libs/pprocessor/src/parse.c index f459ceb..9cb90a2 100644 --- a/libs/pprocessor/src/parse.c +++ b/libs/pprocessor/src/parse.c @@ -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(¤t_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(¤t_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(¤t_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", diff --git a/libs/pprocessor/src/pprocessor.c b/libs/pprocessor/src/pprocessor.c index 8ce17d9..01b4eed 100644 --- a/libs/pprocessor/src/pprocessor.c +++ b/libs/pprocessor/src/pprocessor.c @@ -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; diff --git a/libs/pprocessor/tests/test_unit.c b/libs/pprocessor/tests/test_unit.c index ae367ca..6a2c405 100644 --- a/libs/pprocessor/tests/test_unit.c +++ b/libs/pprocessor/tests/test_unit.c @@ -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}, }; \ No newline at end of file diff --git a/runtime/libcore/include/core_pos.h b/runtime/libcore/include/core_pos.h index 9d076d3..0be3895 100644 --- a/runtime/libcore/include/core_pos.h +++ b/runtime/libcore/include/core_pos.h @@ -10,8 +10,8 @@ typedef struct scc_pos { usize offset; } scc_pos_t; -static inline scc_pos_t scc_pos_init() { - return (scc_pos_t){scc_cstring_new(), 1, 1, 0}; +static inline scc_pos_t scc_pos_create() { + return (scc_pos_t){scc_cstring_create(), 1, 1, 0}; } static inline void scc_pos_next(scc_pos_t *pos) { diff --git a/runtime/libcore/include/core_str.h b/runtime/libcore/include/core_str.h index 7734ad0..864a3ea 100644 --- a/runtime/libcore/include/core_str.h +++ b/runtime/libcore/include/core_str.h @@ -20,11 +20,17 @@ typedef struct scc_cstring { * * @return cstring_t 初始化后的对象 */ -// FIXME need using `init` beacuse it not malloc -static inline scc_cstring_t scc_cstring_new(void) { +static inline scc_cstring_t scc_cstring_create(void) { return (scc_cstring_t){.data = null, .size = 0, .cap = 0}; } +static inline void scc_cstring_init(scc_cstring_t *string) { + Assert(string != null); + string->data = null; + string->size = 0; + string->cap = 0; +} + /** * @brief 从 C 风格字符串创建一个动态字符串副本 * @@ -33,7 +39,7 @@ static inline scc_cstring_t scc_cstring_new(void) { */ static inline scc_cstring_t scc_cstring_from_cstr(const char *s) { if (s == null) { - return scc_cstring_new(); + return scc_cstring_create(); } usize len = 0; diff --git a/runtime/libcore/include/core_stream.h b/runtime/libcore/include/core_stream.h index 18afe3a..06a46b5 100644 --- a/runtime/libcore/include/core_stream.h +++ b/runtime/libcore/include/core_stream.h @@ -123,8 +123,8 @@ scc_probe_stream_t *scc_mem_probe_stream_init(scc_mem_probe_stream_t *stream, * @param owned 是否拥有数据(如果拥有将会自动释放) * @return scc_probe_stream_t* */ -scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length, - cbool owned); +scc_probe_stream_t *scc_mem_probe_stream_alloc(const char *data, usize length, + cbool owned); #endif #endif /* __SMCC_CORE_PROBE_STREAM_H__ */ diff --git a/runtime/libcore/src/stream.c b/runtime/libcore/src/stream.c index de4b7a3..8159807 100644 --- a/runtime/libcore/src/stream.c +++ b/runtime/libcore/src/stream.c @@ -164,8 +164,8 @@ static void scc_owned_mem_stream_drop(scc_probe_stream_t *_stream) { scc_free(stream); } -scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length, - cbool owned) { +scc_probe_stream_t *scc_mem_probe_stream_alloc(const char *data, usize length, + cbool owned) { scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)scc_malloc(sizeof(scc_mem_probe_stream_t)); if (stream == null) {