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:
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
void scc_lex_parse_skip_endline(scc_probe_stream_t *input, scc_pos_t *pos) {
|
void scc_lex_parse_skip_endline(scc_probe_stream_t *input, scc_pos_t *pos) {
|
||||||
Assert(input != null && pos != null);
|
Assert(input != null && pos != null);
|
||||||
scc_probe_stream_reset(input);
|
// scc_probe_stream_reset(input);
|
||||||
int ch = scc_probe_stream_peek(input);
|
int ch = scc_probe_stream_peek(input);
|
||||||
if (ch == '\r') {
|
if (ch == '\r') {
|
||||||
scc_probe_stream_consume(input);
|
scc_probe_stream_next(input);
|
||||||
ch = scc_probe_stream_peek(input);
|
ch = scc_probe_stream_peek(input);
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
scc_probe_stream_consume(input);
|
scc_probe_stream_next(input);
|
||||||
}
|
}
|
||||||
scc_pos_next_line(pos);
|
scc_pos_next_line(pos);
|
||||||
} else if (ch == '\n') {
|
} else if (ch == '\n') {
|
||||||
scc_probe_stream_consume(input);
|
scc_probe_stream_next(input);
|
||||||
scc_pos_next_line(pos);
|
scc_pos_next_line(pos);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARN("not a newline character");
|
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) {
|
void scc_lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos) {
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null);
|
Assert(stream != null && pos != null);
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
while (1) {
|
while (1) {
|
||||||
int ch = scc_probe_stream_peek(stream);
|
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);
|
scc_lex_parse_skip_endline(stream, pos);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
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;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null);
|
Assert(stream != null && pos != null);
|
||||||
int ch;
|
int ch;
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
// FIXME Assertion
|
// FIXME Assertion
|
||||||
Assert(ch == '/');
|
Assert(ch == '/');
|
||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
Assert(ch == '*');
|
Assert(ch == '*');
|
||||||
|
|
||||||
// all ready match `/*`
|
// all ready match `/*`
|
||||||
while (1) {
|
while (1) {
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
|
|
||||||
if (ch == scc_stream_eof) {
|
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);
|
scc_lex_parse_skip_endline(stream, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
if (ch == '*') {
|
if (ch == '*') {
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
if (ch == '/') {
|
if (ch == '/') {
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
return;
|
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) {
|
void scc_lex_parse_skip_whitespace(scc_probe_stream_t *input, scc_pos_t *pos) {
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null);
|
Assert(stream != null && pos != null);
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
while (1) {
|
while (1) {
|
||||||
int ch = scc_probe_stream_peek(stream);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
Assert(base == 2 || base == 8 || base == 10 || base == 16);
|
Assert(base == 2 || base == 8 || base == 10 || base == 16);
|
||||||
scc_probe_stream_reset(input);
|
// scc_probe_stream_reset(input);
|
||||||
int ch, tmp;
|
int ch, tmp;
|
||||||
usize n = 0;
|
usize n = 0;
|
||||||
usize offset = pos->offset;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_probe_stream_consume(input);
|
scc_probe_stream_next(input);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
n = n * base + tmp;
|
n = n * base + tmp;
|
||||||
// TODO number overflow
|
// 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) {
|
int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) {
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null);
|
Assert(stream != null && pos != null);
|
||||||
scc_probe_stream_reset(stream);
|
int ch = scc_probe_stream_next(stream);
|
||||||
int ch = scc_probe_stream_peek(stream);
|
scc_pos_next(pos);
|
||||||
int ret = scc_stream_eof;
|
int ret = scc_stream_eof;
|
||||||
|
|
||||||
if (ch == 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);
|
LOG_WARN("Unexpected character '%c' at begin", ch);
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
// scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
|
||||||
|
|
||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
|
|
||||||
if (ch == scc_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unexpected EOF at middle");
|
LOG_WARN("Unexpected EOF at middle");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (ch == '\\') {
|
} else if (ch == '\\') {
|
||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
if (ch == '0') {
|
if (ch == '0') {
|
||||||
// 数字转义序列
|
// 数字转义序列
|
||||||
@@ -238,7 +237,7 @@ int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
} else {
|
} else {
|
||||||
ret = ch;
|
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);
|
LOG_ERROR("Unclosed character literal '%c' at end, expect `'`", ch);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
goto ERR;
|
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_cstring_t *output) {
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null && output != null);
|
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 ch = scc_probe_stream_peek(stream);
|
||||||
|
|
||||||
Assert(scc_cstring_is_empty(output));
|
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);
|
LOG_WARN("Unexpected character '%c' at begin", ch);
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
|
|
||||||
scc_cstring_t str = scc_cstring_from_cstr("");
|
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;
|
goto ERR;
|
||||||
} else if (ch == '\\') {
|
} else if (ch == '\\') {
|
||||||
// TODO bad practice and maybe bugs here
|
// TODO bad practice and maybe bugs here
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_next(stream);
|
||||||
int val = got_simple_escape(ch);
|
int val = got_simple_escape(ch);
|
||||||
if (val == -1) {
|
if (val == -1) {
|
||||||
LOG_ERROR("Invalid escape character it is \\%c [%d]", ch, ch);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (ch == '"') {
|
} else if (ch == '"') {
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
scc_cstring_append_ch(&str, ch);
|
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) {
|
usize *output) {
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
Assert(stream != null && pos != null && output != null);
|
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 ch = scc_probe_stream_peek(stream);
|
||||||
int base = 10; // 默认十进制
|
int base = 10; // 默认十进制
|
||||||
|
|
||||||
@@ -339,7 +338,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
|
|
||||||
if (ch == '0') {
|
if (ch == '0') {
|
||||||
// 消费 '0'
|
// 消费 '0'
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
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') {
|
if (ch == 'x' || ch == 'X') {
|
||||||
// 十六进制
|
// 十六进制
|
||||||
base = 16;
|
base = 16;
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
} else if (ch == 'b' || ch == 'B') {
|
} else if (ch == 'b' || ch == 'B') {
|
||||||
// 二进制 (C23扩展)
|
// 二进制 (C23扩展)
|
||||||
base = 2;
|
base = 2;
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
} else if (ch >= '0' && ch <= '7') {
|
} 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;
|
usize n;
|
||||||
if (_lex_parse_uint(stream, pos, base, &n) == false) {
|
if (_lex_parse_uint(stream, pos, base, &n) == false) {
|
||||||
// 如果没有匹配任何数字,但输入是 '0',已经处理过了
|
// 如果没有匹配任何数字,但输入是 '0',已经处理过了
|
||||||
@@ -384,7 +383,7 @@ cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
// 单个数字的情况,例如 "1"
|
// 单个数字的情况,例如 "1"
|
||||||
// 我们需要消费这个数字并返回它的值
|
// 我们需要消费这个数字并返回它的值
|
||||||
if (ch >= '1' && ch <= '9') {
|
if (ch >= '1' && ch <= '9') {
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
*output = ch - '0';
|
*output = ch - '0';
|
||||||
return true;
|
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(input != null && pos != null && output != null);
|
||||||
Assert(scc_cstring_is_empty(output));
|
Assert(scc_cstring_is_empty(output));
|
||||||
scc_probe_stream_t *stream = input;
|
scc_probe_stream_t *stream = input;
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
int ch = scc_probe_stream_peek(stream);
|
int ch = scc_probe_stream_peek(stream);
|
||||||
|
|
||||||
if (ch == scc_stream_eof) {
|
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)) {
|
} else if (scc_lex_parse_is_identifier_prefix(ch)) {
|
||||||
while (1) {
|
while (1) {
|
||||||
scc_cstring_append_ch(output, ch);
|
scc_cstring_append_ch(output, ch);
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||||
|
|||||||
@@ -4,12 +4,16 @@
|
|||||||
|
|
||||||
cbool check_char(const char *str, int expect, int *output) {
|
cbool check_char(const char *str, int expect, int *output) {
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
||||||
*output = scc_lex_parse_char(stream, &pos);
|
*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) \
|
#define CHECK_CHAR_VALID(str, expect) \
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
cbool check_identifier(const char *str, const char *expect,
|
cbool check_identifier(const char *str, const char *expect,
|
||||||
scc_cstring_t *output) {
|
scc_cstring_t *output) {
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
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) \
|
#define CHECK_IDENTIFIER_VALID(str, expect) \
|
||||||
do { \
|
do { \
|
||||||
scc_cstring_t _output = scc_cstring_new(); \
|
scc_cstring_t _output = scc_cstring_create(); \
|
||||||
cbool ret = check_identifier(str, expect, &_output); \
|
cbool ret = check_identifier(str, expect, &_output); \
|
||||||
TEST_CHECK(ret == true); \
|
TEST_CHECK(ret == true); \
|
||||||
TEST_CHECK(strcmp(_output.data, expect) == 0); \
|
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) \
|
#define CHECK_IDENTIFIER_INVALID(str) \
|
||||||
do { \
|
do { \
|
||||||
scc_cstring_t _output = scc_cstring_new(); \
|
scc_cstring_t _output = scc_cstring_create(); \
|
||||||
cbool ret = check_identifier(str, NULL, &_output); \
|
cbool ret = check_identifier(str, NULL, &_output); \
|
||||||
TEST_CHECK(ret == false); \
|
TEST_CHECK(ret == false); \
|
||||||
scc_cstring_free(&_output); \
|
scc_cstring_free(&_output); \
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ cbool check(const char *str, usize expect, usize *output) {
|
|||||||
// TODO maybe have other logger
|
// TODO maybe have other logger
|
||||||
(void)(expect);
|
(void)(expect);
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
void check_skip_block_comment(const char *str, const char *expect_remaining) {
|
void check_skip_block_comment(const char *str, const char *expect_remaining) {
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
||||||
|
|
||||||
scc_lex_parse_skip_block_comment(stream, &pos);
|
scc_lex_parse_skip_block_comment(stream, &pos);
|
||||||
|
scc_probe_stream_sync(stream);
|
||||||
|
|
||||||
// Check remaining content
|
// Check remaining content
|
||||||
char buffer[256] = {0};
|
char buffer[256] = {0};
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
void check_skip_line(const char *str, const char *expect_remaining) {
|
void check_skip_line(const char *str, const char *expect_remaining) {
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
||||||
|
|
||||||
scc_lex_parse_skip_line(stream, &pos);
|
scc_lex_parse_skip_line(stream, &pos);
|
||||||
|
scc_probe_stream_sync(stream);
|
||||||
|
|
||||||
// Check remaining content
|
// Check remaining content
|
||||||
char buffer[256] = {0};
|
char buffer[256] = {0};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
cbool check_string(const char *str, const char *expect, scc_cstring_t *output) {
|
cbool check_string(const char *str, const char *expect, scc_cstring_t *output) {
|
||||||
log_set_level(&__default_logger_root, 0);
|
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_mem_probe_stream_t mem_stream;
|
||||||
scc_probe_stream_t *stream =
|
scc_probe_stream_t *stream =
|
||||||
scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false);
|
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) \
|
#define CHECK_STRING_VALID(str, expect) \
|
||||||
do { \
|
do { \
|
||||||
scc_cstring_t _output = scc_cstring_new(); \
|
scc_cstring_t _output = scc_cstring_create(); \
|
||||||
cbool ret = check_string(str, expect, &_output); \
|
cbool ret = check_string(str, expect, &_output); \
|
||||||
TEST_CHECK(ret == true); \
|
TEST_CHECK(ret == true); \
|
||||||
TEST_CHECK(strcmp(_output.data, expect) == 0); \
|
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) \
|
#define CHECK_STRING_INVALID(str) \
|
||||||
do { \
|
do { \
|
||||||
scc_cstring_t _output = scc_cstring_new(); \
|
scc_cstring_t _output = scc_cstring_create(); \
|
||||||
cbool ret = check_string(str, NULL, &_output); \
|
cbool ret = check_string(str, NULL, &_output); \
|
||||||
TEST_CHECK(ret == false); \
|
TEST_CHECK(ret == false); \
|
||||||
scc_cstring_free(&_output); \
|
scc_cstring_free(&_output); \
|
||||||
|
|||||||
@@ -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) {
|
void scc_lexer_init(scc_lexer_t *lexer, scc_probe_stream_t *stream) {
|
||||||
lexer->stream = stream;
|
lexer->stream = stream;
|
||||||
lexer->pos = scc_pos_init();
|
lexer->pos = scc_pos_create();
|
||||||
// FIXME
|
// FIXME
|
||||||
lexer->pos.name = scc_cstring_copy(&stream->name);
|
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);
|
int ch = scc_probe_stream_next(stream);
|
||||||
|
|
||||||
usize n;
|
usize n;
|
||||||
scc_cstring_t str = scc_cstring_new();
|
scc_cstring_t str = scc_cstring_create();
|
||||||
|
|
||||||
if (ch == scc_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LEX_WARN("Unexpected EOF at begin");
|
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");
|
LEX_ERROR("Invalid line number");
|
||||||
goto SKIP_LINE;
|
goto SKIP_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scc_probe_stream_consume(stream) != ' ') {
|
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;
|
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");
|
LEX_ERROR("Invalid `#` line");
|
||||||
goto SKIP_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");
|
LEX_ERROR("Invalid filename");
|
||||||
goto SKIP_LINE;
|
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;
|
token->loc.line = n;
|
||||||
// FIXME memory leak
|
// FIXME memory leak
|
||||||
token->loc.name = scc_cstring_copy(&str);
|
token->loc.name = scc_cstring_copy(&str);
|
||||||
scc_cstring_free(&str);
|
scc_cstring_free(&str);
|
||||||
return;
|
return;
|
||||||
SKIP_LINE:
|
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:
|
ERR:
|
||||||
set_err_token(token);
|
set_err_token(token);
|
||||||
scc_cstring_free(&str);
|
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;
|
type = SCC_TOK_ASSIGN_DIV;
|
||||||
goto double_char;
|
goto double_char;
|
||||||
case '/':
|
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;
|
token->type = SCC_TOK_LINE_COMMENT;
|
||||||
goto END;
|
goto END;
|
||||||
case '*':
|
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;
|
token->type = SCC_TOK_BLOCK_COMMENT;
|
||||||
goto END;
|
goto END;
|
||||||
default:
|
default:
|
||||||
@@ -369,7 +375,8 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\n':
|
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;
|
token->type = SCC_TOK_BLANK;
|
||||||
goto END;
|
goto END;
|
||||||
case '#':
|
case '#':
|
||||||
@@ -384,7 +391,9 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
case '\'': {
|
case '\'': {
|
||||||
token->loc = lexer->pos;
|
token->loc = lexer->pos;
|
||||||
token->type = SCC_TOK_CHAR_LITERAL;
|
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) {
|
if (ch == scc_stream_eof) {
|
||||||
LEX_ERROR("Unexpected character literal");
|
LEX_ERROR("Unexpected character literal");
|
||||||
token->type = SCC_TOK_UNKNOWN;
|
token->type = SCC_TOK_UNKNOWN;
|
||||||
@@ -396,8 +405,10 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
case '"': {
|
case '"': {
|
||||||
token->loc = lexer->pos;
|
token->loc = lexer->pos;
|
||||||
token->type = SCC_TOK_STRING_LITERAL;
|
token->type = SCC_TOK_STRING_LITERAL;
|
||||||
scc_cstring_t output = scc_cstring_new();
|
scc_cstring_t output = scc_cstring_create();
|
||||||
if (scc_lex_parse_string(lexer->stream, &lexer->pos, &output) == true) {
|
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.data = scc_cstring_as_cstr(&output);
|
||||||
token->value.cstr.len = scc_cstring_len(&output);
|
token->value.cstr.len = scc_cstring_len(&output);
|
||||||
} else {
|
} else {
|
||||||
@@ -414,7 +425,9 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
token->loc = lexer->pos;
|
token->loc = lexer->pos;
|
||||||
token->type = SCC_TOK_INT_LITERAL;
|
token->type = SCC_TOK_INT_LITERAL;
|
||||||
usize output;
|
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;
|
token->value.n = output;
|
||||||
} else {
|
} else {
|
||||||
LEX_ERROR("Unexpected number literal");
|
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 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
|
||||||
case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
|
case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
scc_cstring_t str = scc_cstring_new();
|
scc_cstring_t str = scc_cstring_create();
|
||||||
cbool ret = scc_lex_parse_identifier(lexer->stream, &lexer->pos, &str);
|
scc_probe_stream_reset(stream);
|
||||||
|
cbool ret = scc_lex_parse_identifier(stream, &lexer->pos, &str);
|
||||||
|
scc_probe_stream_sync(stream);
|
||||||
Assert(ret == true);
|
Assert(ret == true);
|
||||||
|
|
||||||
int res = keyword_cmp(scc_cstring_as_cstr(&str), scc_cstring_len(&str));
|
int res = keyword_cmp(scc_cstring_as_cstr(&str), scc_cstring_len(&str));
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ int main(int argc, char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
// FIXME it is a hack lexer_logger
|
// FIXME it is a hack lexer_logger
|
||||||
log_set_level(&__smcc_lexer_log, LOG_LEVEL_NOTSET);
|
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__;
|
const char *file_name = __FILE__;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SCC_PP_MACRO_OBJECT, // 对象宏
|
SCC_PP_MACRO_OBJECT, // 对象宏
|
||||||
SCC_PP_MACRO_FUNCTION, // 函数宏
|
SCC_PP_MACRO_FUNCTION, // 函数宏
|
||||||
|
SCC_PP_MACRO_NONE, // 不是宏
|
||||||
} scc_pp_macro_type_t;
|
} scc_pp_macro_type_t;
|
||||||
|
|
||||||
typedef SCC_VEC(scc_cstring_t) scc_pp_macro_list_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
|
* @return 找到的宏对象指针,未找到返回NULL
|
||||||
*/
|
*/
|
||||||
scc_pp_macro_t *scc_pp_macro_table_get(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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从预处理器中删除宏
|
* @brief 从预处理器中删除宏
|
||||||
|
|||||||
@@ -4,22 +4,22 @@
|
|||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
/// https://cppreference.cn/w/c/preprocessor
|
/// https://cppreference.cn/w/c/preprocessor
|
||||||
#define SCC_PP_INST_TOKEN \
|
#define SCC_PP_INST_TOKEN \
|
||||||
X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \
|
X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \
|
||||||
X(elif , SCC_PP_STD, SCC_PP_TOK_UNDEF ) \
|
X(elif , SCC_PP_STD, SCC_PP_TOK_ELIF ) \
|
||||||
X(elifdef , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \
|
X(elifdef , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \
|
||||||
X(elifndef , SCC_PP_STD, SCC_PP_TOK_IF ) \
|
X(elifndef , SCC_PP_STD, SCC_PP_TOK_ELIFNDEF ) \
|
||||||
X(else , SCC_PP_STD, SCC_PP_TOK_IFDEF ) \
|
X(else , SCC_PP_STD, SCC_PP_TOK_ELSE ) \
|
||||||
X(embed , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \
|
X(embed , SCC_PP_STD, SCC_PP_TOK_EMBED ) \
|
||||||
X(endif , SCC_PP_STD, SCC_PP_TOK_ELSE ) \
|
X(endif , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \
|
||||||
X(error , SCC_PP_STD, SCC_PP_TOK_ELIF ) \
|
X(error , SCC_PP_STD, SCC_PP_TOK_ERROR ) \
|
||||||
X(if , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \
|
X(if , SCC_PP_STD, SCC_PP_TOK_IF ) \
|
||||||
X(ifdef , SCC_PP_C23, SCC_PP_TOK_ELIFNDEF ) \
|
X(ifdef , SCC_PP_C23, SCC_PP_TOK_IFDEF ) \
|
||||||
X(ifndef , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \
|
X(ifndef , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \
|
||||||
X(include , SCC_PP_STD, SCC_PP_TOK_LINE ) \
|
X(include , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \
|
||||||
X(line , SCC_PP_C23, SCC_PP_TOK_EMBED ) \
|
X(line , SCC_PP_C23, SCC_PP_TOK_LINE ) \
|
||||||
X(pragma , SCC_PP_STD, SCC_PP_TOK_ERROR ) \
|
X(pragma , SCC_PP_STD, SCC_PP_TOK_PRAGMA ) \
|
||||||
X(undef , SCC_PP_C23, SCC_PP_TOK_WARNING ) \
|
X(undef , SCC_PP_C23, SCC_PP_TOK_UNDEF ) \
|
||||||
X(warning , SCC_PP_STD, SCC_PP_TOK_PRAMA ) \
|
X(warning , SCC_PP_STD, SCC_PP_TOK_WARNING ) \
|
||||||
// END
|
// END
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <pp_parse.h>
|
#include <pp_parse.h>
|
||||||
|
|
||||||
static inline void scc_generate_cstr(scc_cstring_t *buff) {
|
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, '\"');
|
scc_cstring_append_ch(&out_buff, '\"');
|
||||||
// TODO it is too simple
|
// TODO it is too simple
|
||||||
scc_cstring_append(&out_buff, buff);
|
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)); \
|
scc_cstring_append(out_buff, &scc_vec_at(*list, font)); \
|
||||||
}
|
}
|
||||||
// for # ## to generator string
|
// 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) {
|
scc_cstring_t *out_buff) {
|
||||||
for (usize i = 0; i < list->size; ++i) {
|
for (usize i = 0; i < list->size; ++i) {
|
||||||
if (SCC_PP_IS_LIST_BLANK(i + 1)) {
|
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) {
|
if (i < list->size) {
|
||||||
scc_generate_cstr(&scc_vec_at(*list, i));
|
scc_generate_cstr(&scc_vec_at(*list, i));
|
||||||
} else {
|
} else {
|
||||||
LOG_WARN("# need a valid literator");
|
LOG_ERROR("# need a valid literator");
|
||||||
break;
|
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) {
|
scc_cstring_t *out_buff) {
|
||||||
Assert(macro->type == SCC_PP_MACRO_OBJECT && macro->params.size == 0);
|
Assert(macro->type == SCC_PP_MACRO_OBJECT && macro->params.size == 0);
|
||||||
Assert(scc_cstring_is_empty(out_buff) == true);
|
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,
|
cbool scc_pp_expand_function_macro(const scc_pp_macro_t *macro,
|
||||||
scc_pp_macro_list_t *origin_params,
|
const scc_pp_macro_list_t *origin_params,
|
||||||
scc_pp_macro_list_t *params,
|
scc_pp_macro_list_t *params,
|
||||||
scc_cstring_t *out_buff) {
|
scc_cstring_t *out_buff) {
|
||||||
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
|
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
|
||||||
Assert(out_buff != null);
|
Assert(out_buff != null);
|
||||||
Assert(scc_cstring_is_empty(out_buff) == true);
|
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_pp_macro_list_t list;
|
||||||
scc_vec_init(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) {
|
for (usize j = 0; j < macro->params.size; ++j) {
|
||||||
if (scc_strcmp(
|
if (scc_strcmp(
|
||||||
scc_cstring_as_cstr(&scc_vec_at(macro->replaces, i)),
|
scc_cstring_as_cstr(&scc_vec_at(macro->replaces, i)),
|
||||||
scc_cstring_as_cstr(&scc_vec_at(macro->params, j))) == 0) {
|
scc_cstring_as_cstr(&scc_vec_at(macro->params, j))) != 0) {
|
||||||
Assert(&scc_vec_at(*params, j) != null);
|
continue;
|
||||||
scc_vec_push(list, scc_cstring_copy(&scc_vec_at(*params, j)));
|
}
|
||||||
|
if (params->size == 0) {
|
||||||
|
scc_vec_push(list, scc_cstring_from_cstr(""));
|
||||||
goto END;
|
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)));
|
scc_vec_push(list, scc_cstring_copy(&scc_vec_at(macro->replaces, i)));
|
||||||
END:;
|
END:;
|
||||||
@@ -110,10 +115,10 @@ typedef struct {
|
|||||||
scc_pp_macro_table_t *macros;
|
scc_pp_macro_table_t *macros;
|
||||||
scc_pp_macro_table_t painted_blue; // 正在展开的宏
|
scc_pp_macro_table_t painted_blue; // 正在展开的宏
|
||||||
int depth;
|
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_t *macro) {
|
||||||
// 添加到活动宏集合
|
// 添加到活动宏集合
|
||||||
scc_pp_macro_table_set(&state->painted_blue,
|
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_t *macro) {
|
||||||
// 从活动宏移除,添加到禁用宏
|
// 从活动宏移除,添加到禁用宏
|
||||||
scc_pp_macro_table_remove(&state->painted_blue, ¯o->name);
|
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) {
|
scc_pp_macro_t *macro) {
|
||||||
return scc_pp_macro_table_get(&state->painted_blue, ¯o->name) == null;
|
return scc_pp_macro_table_get(&state->painted_blue, ¯o->name) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cbool _scc_pp_expand_macro(scc_probe_stream_t *stream,
|
typedef struct {
|
||||||
macro_expansion_state_t *state,
|
scc_cstring_t identifier;
|
||||||
scc_probe_stream_t **out_stream);
|
scc_pp_macro_list_t args;
|
||||||
|
} scc_expand_unit_t;
|
||||||
|
|
||||||
static cbool expanded_buffer(const scc_cstring_t *in, scc_cstring_t *out,
|
void scc_pp_parse_expand_macro(scc_probe_stream_t *stream, scc_pos_t *pos,
|
||||||
macro_expansion_state_t *state) {
|
scc_expand_unit_t *unit) {
|
||||||
scc_probe_stream_t *in_stream = scc_mem_probe_stream_new(
|
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);
|
scc_cstring_as_cstr(in), scc_cstring_len(in), false);
|
||||||
|
|
||||||
// rescanning
|
|
||||||
int ch;
|
int ch;
|
||||||
|
scc_pos_t pos;
|
||||||
|
scc_expand_unit_t unit;
|
||||||
while ((ch = scc_probe_stream_peek(in_stream)) != scc_stream_eof) {
|
while ((ch = scc_probe_stream_peek(in_stream)) != scc_stream_eof) {
|
||||||
if (scc_lex_parse_is_identifier_prefix(ch)) {
|
if (scc_lex_parse_is_identifier_prefix(ch)) {
|
||||||
// 递归检查
|
// 递归检查
|
||||||
scc_probe_stream_t *out_stream;
|
scc_cstring_t expanded_buffer = scc_cstring_create();
|
||||||
if (_scc_pp_expand_macro(in_stream, state, &out_stream) == false) {
|
scc_pp_parse_expand_macro(in_stream, &pos, &unit);
|
||||||
scc_cstring_free(out);
|
scc_probe_stream_reset(in_stream);
|
||||||
|
if (expand_macro(&unit, &expanded_buffer, state) == false) {
|
||||||
|
scc_cstring_free(&expanded_buffer);
|
||||||
return false;
|
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 {
|
} else {
|
||||||
scc_cstring_append_ch(out, scc_probe_stream_consume(in_stream));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// static cbool scc_pp_expand_macro_impl(scc_probe_stream_t *stream,
|
||||||
* 1. 参数先展开
|
// scc_expansion_ctx_t *ctx, scc_pos_t
|
||||||
* 2. 替换后重扫描
|
// *pos, scc_cstring_t *output) {
|
||||||
* 3. 蓝色集合中不展开
|
// // TODO self position and it maybe is a stack on #include ?
|
||||||
* 4. #, ## 不展开
|
// // 递归扫描
|
||||||
* 5. 最后的括号要检查
|
// if (ctx->depth-- <= 0) {
|
||||||
*/
|
// scc_cstring_free(output);
|
||||||
static cbool _scc_pp_expand_macro(scc_probe_stream_t *stream,
|
// return false;
|
||||||
macro_expansion_state_t *state,
|
// }
|
||||||
scc_probe_stream_t **out_stream) {
|
// cbool ret;
|
||||||
// TODO self position and it maybe is a stack on #include ?
|
// scc_pp_macro_table_t *macros = ctx->macros;
|
||||||
// 递归扫描
|
|
||||||
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();
|
|
||||||
|
|
||||||
cbool ret;
|
// scc_cstring_t identifier = scc_cstring_create();
|
||||||
ret = scc_lex_parse_identifier(stream, &pos, &identifier);
|
// ret = scc_lex_parse_identifier(stream, pos, &identifier);
|
||||||
Assert(ret == true);
|
// 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. 不是宏,直接输出标识符
|
// // 1. 不是宏,直接输出标识符
|
||||||
if (macro == null) {
|
// if (macro == null) {
|
||||||
// 不是宏,直接输出
|
// // 不是宏,直接输出
|
||||||
usize length = scc_cstring_len(&identifier);
|
// usize length = scc_cstring_len(&identifier);
|
||||||
*out_stream = scc_mem_probe_stream_new(
|
// *out_stream = scc_mem_probe_stream_alloc(
|
||||||
scc_cstring_move_cstr(&identifier), length, true);
|
// scc_cstring_move_cstr(&identifier), length, true);
|
||||||
return true;
|
// return true;
|
||||||
} else {
|
// } else {
|
||||||
scc_cstring_free(&identifier);
|
// scc_cstring_free(&identifier);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 收集参数(如果是函数宏)
|
// // 收集参数(如果是函数宏)
|
||||||
scc_pp_macro_list_t params;
|
// scc_pp_macro_list_t params;
|
||||||
scc_vec_init(params);
|
// scc_pp_macro_list_t expanded_params;
|
||||||
if (macro->type == SCC_PP_MACRO_FUNCTION) {
|
// scc_vec_init(params);
|
||||||
// TODO when expand need check another func with () at the end
|
// scc_vec_init(expanded_params);
|
||||||
scc_lex_parse_skip_whitespace(stream, &pos);
|
// if (macro->type == SCC_PP_MACRO_FUNCTION) {
|
||||||
if (scc_probe_stream_peek(stream) != '(') {
|
// // TODO when expand need check another func with () at the end
|
||||||
goto ORIGIN;
|
// scc_lex_parse_skip_whitespace(stream, &pos);
|
||||||
}
|
// if (scc_probe_stream_peek(stream) != '(') {
|
||||||
ret = scc_pp_parse_macro_arguments(stream, ¶ms);
|
// goto ORIGIN;
|
||||||
Assert(ret == true);
|
// }
|
||||||
}
|
// ret = scc_pp_parse_macro_arguments(stream, ¶ms);
|
||||||
|
// Assert(ret == true);
|
||||||
|
|
||||||
// 2. 检查到重复展开跳过
|
// // expand params fisrt and recursive
|
||||||
// 检查是否可以展开
|
// for (usize i = 0; i < params.size; ++i) {
|
||||||
if (!can_expand_macro(state, macro)) {
|
// scc_cstring_t param = scc_vec_at(params, i);
|
||||||
ORIGIN:
|
// scc_cstring_t out = scc_cstring_create();
|
||||||
// 输出原始调用
|
// expand_buffer(¶m, &out, ctx);
|
||||||
scc_cstring_t original = scc_cstring_new();
|
// scc_vec_push(expanded_params, out);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始展开
|
// // 2. 检查到重复展开跳过
|
||||||
scc_cstring_t expanded = scc_cstring_new();
|
// // 检查是否可以展开
|
||||||
if (macro->type == SCC_PP_MACRO_OBJECT) {
|
// if (!can_expand_macro(ctx, macro)) {
|
||||||
ret = scc_pp_expand_object_macro(macro, &expanded);
|
// ORIGIN:
|
||||||
Assert(ret == true);
|
// // 输出原始调用
|
||||||
goto RESCANNING;
|
// scc_cstring_t original = scc_cstring_create();
|
||||||
} else if (macro->type != SCC_PP_MACRO_FUNCTION) {
|
// scc_cstring_append(&original, ¯o->name);
|
||||||
TODO();
|
// 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);
|
// // 将展开内容变换成stream并递归展开
|
||||||
// expand params fisrt and recursive
|
// scc_cstring_t rescanned = scc_cstring_create();
|
||||||
for (usize i = 0; i < params.size; ++i) {
|
// enter_macro_expansion(ctx, macro);
|
||||||
scc_cstring_t param = scc_vec_at(params, i);
|
// expand_buffer(&expanded, &rescanned, ctx);
|
||||||
scc_cstring_t out = scc_cstring_new();
|
// leave_macro_expansion(ctx, macro);
|
||||||
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);
|
|
||||||
|
|
||||||
RESCANNING:
|
// scc_cstring_free(&expanded);
|
||||||
// 重新扫描展开结果
|
// // TODO memory leak
|
||||||
// 将展开内容变换成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);
|
// *out_stream = scc_mem_probe_stream_alloc(scc_cstring_as_cstr(&rescanned),
|
||||||
*out_stream = scc_mem_probe_stream_new(scc_cstring_as_cstr(&rescanned),
|
// scc_cstring_len(&rescanned),
|
||||||
scc_cstring_len(&rescanned), true);
|
// true);
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
cbool scc_pp_expand_macro(scc_probe_stream_t *stream,
|
cbool scc_pp_expand_macro(scc_probe_stream_t *stream,
|
||||||
scc_pp_macro_table_t *macros,
|
scc_pp_macro_table_t *macros,
|
||||||
scc_probe_stream_t **out_stream, int depth) {
|
scc_probe_stream_t **out_stream, int depth) {
|
||||||
Assert(depth > 0 && stream != null && macros != null && out_stream != null);
|
Assert(depth > 0 && stream != null && macros != null && out_stream != null);
|
||||||
macro_expansion_state_t state;
|
scc_expansion_ctx_t state;
|
||||||
state.depth = depth;
|
state.depth = depth;
|
||||||
scc_pp_marco_table_init(&state.painted_blue);
|
scc_pp_marco_table_init(&state.painted_blue);
|
||||||
state.macros = macros;
|
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);
|
scc_pp_macro_table_drop(&state.painted_blue);
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_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);
|
return scc_hashtable_get(&pp->table, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,19 +51,19 @@ static inline void try_to_cut_list(scc_pp_macro_list_t *list,
|
|||||||
scc_cstring_t *buff) {
|
scc_cstring_t *buff) {
|
||||||
if (scc_cstring_len(buff) != 0) {
|
if (scc_cstring_len(buff) != 0) {
|
||||||
scc_vec_push(*list, *buff);
|
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,
|
cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream,
|
||||||
scc_pp_macro_list_t *list) {
|
scc_pp_macro_list_t *list) {
|
||||||
Assert(stream != null && list != null);
|
Assert(stream != null && list != null);
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
|
|
||||||
scc_vec_init(*list);
|
scc_vec_init(*list);
|
||||||
scc_cstring_t replacement = scc_cstring_new();
|
scc_cstring_t replacement = scc_cstring_create();
|
||||||
int ch;
|
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) {
|
while ((ch = scc_probe_stream_peek(stream)) != scc_stream_eof) {
|
||||||
if (scc_lex_parse_is_endline(ch)) {
|
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);
|
try_to_cut_list(list, &replacement);
|
||||||
} else if (ch == '#') {
|
} else if (ch == '#') {
|
||||||
// 处理 # 和 ## 操作符
|
// 处理 # 和 ## 操作符
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
try_to_cut_list(list, &replacement);
|
try_to_cut_list(list, &replacement);
|
||||||
|
|
||||||
scc_cstring_append_ch(&replacement, '#');
|
scc_cstring_append_ch(&replacement, '#');
|
||||||
if (scc_probe_stream_peek(stream) == '#') {
|
if (scc_probe_stream_peek(stream) == '#') {
|
||||||
// ## 连接操作符
|
// ## 连接操作符
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_cstring_append_ch(&replacement, '#');
|
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, ' ');
|
scc_cstring_append_ch(&replacement, ' ');
|
||||||
try_to_cut_list(list, &replacement);
|
try_to_cut_list(list, &replacement);
|
||||||
} else {
|
} else {
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
scc_cstring_append_ch(&replacement, (char)ch);
|
scc_cstring_append_ch(&replacement, (char)ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scc_cstring_len(&replacement) != 0) {
|
if (scc_cstring_len(&replacement) != 0) {
|
||||||
scc_vec_push(*list, replacement);
|
scc_vec_push(*list, replacement);
|
||||||
replacement = scc_cstring_new();
|
replacement = scc_cstring_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (usize i = 0; i < list->size; ++i) {
|
// 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);
|
scc_vec_init(*args);
|
||||||
int ch;
|
int ch;
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
|
|
||||||
// 跳过 '('
|
// 跳过 '('
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
if (ch != '(') {
|
if (ch != '(') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream); // 消费 '('
|
scc_probe_stream_next(stream); // 消费 '('
|
||||||
|
|
||||||
int paren_depth = 1;
|
int paren_depth = 1;
|
||||||
scc_cstring_t current_arg = scc_cstring_new();
|
scc_cstring_t current_arg = scc_cstring_create();
|
||||||
scc_pos_t pos = scc_pos_init();
|
scc_pos_t pos = scc_pos_create();
|
||||||
|
|
||||||
while (paren_depth > 0) {
|
while (paren_depth > 0) {
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
@@ -142,23 +142,23 @@ cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream,
|
|||||||
if (ch == '(') {
|
if (ch == '(') {
|
||||||
paren_depth++;
|
paren_depth++;
|
||||||
scc_cstring_append_ch(¤t_arg, (char)ch);
|
scc_cstring_append_ch(¤t_arg, (char)ch);
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
} else if (ch == ')') {
|
} else if (ch == ')') {
|
||||||
paren_depth--;
|
paren_depth--;
|
||||||
if (paren_depth > 0) {
|
if (paren_depth > 0) {
|
||||||
scc_cstring_append_ch(¤t_arg, (char)ch);
|
scc_cstring_append_ch(¤t_arg, (char)ch);
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
} else if (ch == ',' && paren_depth == 1) {
|
} else if (ch == ',' && paren_depth == 1) {
|
||||||
// 参数分隔符
|
// 参数分隔符
|
||||||
scc_vec_push(*args, current_arg);
|
scc_vec_push(*args, current_arg);
|
||||||
current_arg = scc_cstring_new();
|
current_arg = scc_cstring_create();
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
// 跳过参数后的空白
|
// 跳过参数后的空白
|
||||||
scc_lex_parse_skip_whitespace(stream, &pos);
|
scc_lex_parse_skip_whitespace(stream, &pos);
|
||||||
} else {
|
} else {
|
||||||
scc_cstring_append_ch(¤t_arg, (char)ch);
|
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,
|
static cbool safe_skip_backspace_if_endline(scc_probe_stream_t *stream,
|
||||||
scc_pos_t *pos) {
|
scc_pos_t *pos) {
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
int ch = scc_probe_stream_peek(stream);
|
int ch = scc_probe_stream_peek(stream);
|
||||||
// FIXME maybe it not correct
|
// FIXME maybe it not correct
|
||||||
while (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') {
|
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);
|
scc_lex_parse_skip_endline(stream, pos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
}
|
}
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
return false;
|
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) {
|
scc_pp_macro_table_t *macros) {
|
||||||
Assert(stream != null);
|
Assert(stream != null);
|
||||||
|
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
// 跳过 '#' 和后续空白
|
// 跳过 '#' 和后续空白
|
||||||
if (scc_probe_stream_peek(stream) != '#') {
|
if (scc_probe_stream_peek(stream) != '#') {
|
||||||
LOG_WARN("Invalid directive");
|
LOG_WARN("Invalid directive");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_next(stream);
|
||||||
if (safe_skip_backspace_if_endline(stream, pos))
|
if (safe_skip_backspace_if_endline(stream, pos))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 解析指令名称
|
// 解析指令名称
|
||||||
scc_cstring_t directive = scc_cstring_new();
|
scc_cstring_t directive = scc_cstring_create();
|
||||||
if (!scc_lex_parse_identifier(stream, pos, &directive)) {
|
if (!scc_lex_parse_identifier(stream, pos, &directive)) {
|
||||||
goto ERR;
|
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_pp_token_t token = keyword_cmp(scc_cstring_as_cstr(&directive),
|
||||||
scc_cstring_len(&directive));
|
scc_cstring_len(&directive));
|
||||||
|
|
||||||
scc_cstring_t name = scc_cstring_new();
|
scc_cstring_t name = scc_cstring_create();
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case SCC_PP_TOK_DEFINE: {
|
case SCC_PP_TOK_DEFINE: {
|
||||||
if (!scc_lex_parse_identifier(stream, pos, &name)) {
|
if (!scc_lex_parse_identifier(stream, pos, &name)) {
|
||||||
scc_cstring_free(&name);
|
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否是函数宏:宏名后是否直接跟着 '('(没有空白字符)
|
// 检查是否是函数宏:宏名后是否直接跟着 '('(没有空白字符)
|
||||||
scc_probe_stream_reset(stream);
|
// scc_probe_stream_reset(stream);
|
||||||
int ch = scc_probe_stream_peek(stream);
|
int ch = scc_probe_stream_peek(stream);
|
||||||
cbool has_whitespace = scc_lex_parse_is_whitespace(ch);
|
cbool has_whitespace = scc_lex_parse_is_whitespace(ch);
|
||||||
if (has_whitespace && safe_skip_backspace_if_endline(stream, pos)) {
|
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);
|
ch = scc_probe_stream_peek(stream);
|
||||||
if (ch == ')') {
|
if (ch == ')') {
|
||||||
scc_probe_stream_consume(stream); // 消费 ')'
|
scc_probe_stream_next(stream); // 消费 ')'
|
||||||
}
|
}
|
||||||
if (safe_skip_backspace_if_endline(stream, pos)) {
|
if (safe_skip_backspace_if_endline(stream, pos)) {
|
||||||
goto FREE;
|
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_parse_macro_replace_list(stream, &replacement);
|
||||||
scc_pp_add_object_macro(macros, &name, &replacement);
|
scc_pp_add_object_macro(macros, &name, &replacement);
|
||||||
}
|
}
|
||||||
scc_cstring_free(&name);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_PP_TOK_UNDEF: {
|
case SCC_PP_TOK_UNDEF: {
|
||||||
if (scc_lex_parse_identifier(stream, pos, &name)) {
|
if (scc_lex_parse_identifier(stream, pos, &name)) {
|
||||||
// TODO ret value
|
cbool ret = scc_pp_macro_table_remove(macros, &name);
|
||||||
scc_pp_macro_table_remove(macros, &name);
|
Assert(ret == true);
|
||||||
}
|
}
|
||||||
break;
|
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_EMBED:
|
||||||
case SCC_PP_TOK_ERROR:
|
case SCC_PP_TOK_ERROR:
|
||||||
case SCC_PP_TOK_WARNING:
|
case SCC_PP_TOK_WARNING:
|
||||||
case SCC_PP_TOK_PRAMA:
|
case SCC_PP_TOK_PRAGMA:
|
||||||
// 暂时跳过这一行
|
// 暂时跳过这一行
|
||||||
scc_lex_parse_skip_line(stream, pos);
|
scc_lex_parse_skip_line(stream, pos);
|
||||||
|
TODO();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_WARN("Unknown preprocessor directive: %s",
|
LOG_WARN("Unknown preprocessor directive: %s",
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ RETRY:
|
|||||||
if (ch == '#') {
|
if (ch == '#') {
|
||||||
scc_pp_parse_directive(stream->input, &stream->pos,
|
scc_pp_parse_directive(stream->input, &stream->pos,
|
||||||
&stream->self->macro_table);
|
&stream->self->macro_table);
|
||||||
|
scc_probe_stream_sync(stream->input);
|
||||||
goto RETRY;
|
goto RETRY;
|
||||||
} else if (scc_lex_parse_is_identifier_prefix(ch)) {
|
} else if (scc_lex_parse_is_identifier_prefix(ch)) {
|
||||||
cbool ret =
|
cbool ret =
|
||||||
@@ -44,9 +45,13 @@ RETRY:
|
|||||||
} else if (scc_probe_stream_next(stream->input) == '/') {
|
} else if (scc_probe_stream_next(stream->input) == '/') {
|
||||||
ch = scc_probe_stream_peek(stream->input);
|
ch = scc_probe_stream_peek(stream->input);
|
||||||
if (ch == '/') {
|
if (ch == '/') {
|
||||||
|
scc_probe_stream_reset(stream->input);
|
||||||
scc_lex_parse_skip_line(stream->input, &stream->pos);
|
scc_lex_parse_skip_line(stream->input, &stream->pos);
|
||||||
|
scc_probe_stream_sync(stream->input);
|
||||||
} else if (ch == '*') {
|
} else if (ch == '*') {
|
||||||
|
scc_probe_stream_reset(stream->input);
|
||||||
scc_lex_parse_skip_block_comment(stream->input, &stream->pos);
|
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->input = input;
|
||||||
|
|
||||||
stream->tmp_stream = null;
|
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.name = scc_cstring_from_cstr("pp_stream");
|
||||||
stream->stream.consume = pp_stream_read_char;
|
stream->stream.consume = pp_stream_read_char;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ static cbool process_input(const char *input, scc_cstring_t *output) {
|
|||||||
|
|
||||||
// 获取输出结果
|
// 获取输出结果
|
||||||
int ch;
|
int ch;
|
||||||
*output = scc_cstring_new();
|
*output = scc_cstring_create();
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = scc_probe_stream_consume(output_stream);
|
ch = scc_probe_stream_consume(output_stream);
|
||||||
if (ch == scc_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
@@ -104,6 +104,17 @@ static void test_define_nested_macros(void) {
|
|||||||
"((1 + 1) + 1)\n");
|
"((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) {
|
static void hard_test_define_func_macros(void) {
|
||||||
TEST_CASE("func_macros_hard with pp_01");
|
TEST_CASE("func_macros_hard with pp_01");
|
||||||
CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n"
|
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"
|
"#define M3(x) x\n"
|
||||||
"M3(M3(M2)(0))\n",
|
"M3(M3(M2)(0))\n",
|
||||||
"M1(0 + 1)\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) {
|
static void test_conditional_compilation(void) {
|
||||||
@@ -177,6 +209,7 @@ TEST_LIST = {
|
|||||||
TEST_LIST_CASE(test_define_stringify_operator),
|
TEST_LIST_CASE(test_define_stringify_operator),
|
||||||
TEST_LIST_CASE(test_define_concat_operator),
|
TEST_LIST_CASE(test_define_concat_operator),
|
||||||
TEST_LIST_CASE(test_define_nested_macros),
|
TEST_LIST_CASE(test_define_nested_macros),
|
||||||
|
TEST_LIST_CASE(test_undef_macros),
|
||||||
TEST_LIST_CASE(hard_test_define_func_macros),
|
TEST_LIST_CASE(hard_test_define_func_macros),
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
@@ -10,8 +10,8 @@ typedef struct scc_pos {
|
|||||||
usize offset;
|
usize offset;
|
||||||
} scc_pos_t;
|
} scc_pos_t;
|
||||||
|
|
||||||
static inline scc_pos_t scc_pos_init() {
|
static inline scc_pos_t scc_pos_create() {
|
||||||
return (scc_pos_t){scc_cstring_new(), 1, 1, 0};
|
return (scc_pos_t){scc_cstring_create(), 1, 1, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_pos_next(scc_pos_t *pos) {
|
static inline void scc_pos_next(scc_pos_t *pos) {
|
||||||
|
|||||||
@@ -20,11 +20,17 @@ typedef struct scc_cstring {
|
|||||||
*
|
*
|
||||||
* @return cstring_t 初始化后的对象
|
* @return cstring_t 初始化后的对象
|
||||||
*/
|
*/
|
||||||
// FIXME need using `init` beacuse it not malloc
|
static inline scc_cstring_t scc_cstring_create(void) {
|
||||||
static inline scc_cstring_t scc_cstring_new(void) {
|
|
||||||
return (scc_cstring_t){.data = null, .size = 0, .cap = 0};
|
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 风格字符串创建一个动态字符串副本
|
* @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) {
|
static inline scc_cstring_t scc_cstring_from_cstr(const char *s) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return scc_cstring_new();
|
return scc_cstring_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
usize len = 0;
|
usize len = 0;
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ scc_probe_stream_t *scc_mem_probe_stream_init(scc_mem_probe_stream_t *stream,
|
|||||||
* @param owned 是否拥有数据(如果拥有将会自动释放)
|
* @param owned 是否拥有数据(如果拥有将会自动释放)
|
||||||
* @return scc_probe_stream_t*
|
* @return scc_probe_stream_t*
|
||||||
*/
|
*/
|
||||||
scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length,
|
scc_probe_stream_t *scc_mem_probe_stream_alloc(const char *data, usize length,
|
||||||
cbool owned);
|
cbool owned);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __SMCC_CORE_PROBE_STREAM_H__ */
|
#endif /* __SMCC_CORE_PROBE_STREAM_H__ */
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ static void scc_owned_mem_stream_drop(scc_probe_stream_t *_stream) {
|
|||||||
scc_free(stream);
|
scc_free(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length,
|
scc_probe_stream_t *scc_mem_probe_stream_alloc(const char *data, usize length,
|
||||||
cbool owned) {
|
cbool owned) {
|
||||||
scc_mem_probe_stream_t *stream =
|
scc_mem_probe_stream_t *stream =
|
||||||
(scc_mem_probe_stream_t *)scc_malloc(sizeof(scc_mem_probe_stream_t));
|
(scc_mem_probe_stream_t *)scc_malloc(sizeof(scc_mem_probe_stream_t));
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user