feat(lex_parser): rename functions and update header guard prefix
- Change header guard from `__SMCC_LEX_PARSER_H__` to `__SCC_LEX_PARSER_H__` - Prefix all lexer functions with `scc_` (e.g., `lex_parse_char` → `scc_lex_parse_char`) - Add new helper function `scc_lex_parse_is_identifier_header` - Update references in source and test files to use new function names - Replace `core_stream_eof` with `scc_stream_eof` for consistency
This commit is contained in:
@@ -1,26 +1,31 @@
|
|||||||
#ifndef __SMCC_LEX_PARSER_H__
|
#ifndef __SCC_LEX_PARSER_H__
|
||||||
#define __SMCC_LEX_PARSER_H__
|
#define __SCC_LEX_PARSER_H__
|
||||||
|
|
||||||
#include <libcore.h>
|
#include <libcore.h>
|
||||||
|
|
||||||
static inline cbool lex_parse_is_endline(int ch) {
|
static inline cbool scc_lex_parse_is_endline(int ch) {
|
||||||
return ch == '\n' || ch == '\r';
|
return ch == '\n' || ch == '\r';
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline cbool lex_parse_is_whitespace(int ch) {
|
static inline cbool scc_lex_parse_is_whitespace(int ch) {
|
||||||
return ch == ' ' || ch == '\t';
|
return ch == ' ' || ch == '\t';
|
||||||
}
|
}
|
||||||
|
|
||||||
int lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos);
|
static inline cbool scc_lex_parse_is_identifier_header(int ch) {
|
||||||
cbool lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos,
|
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
|
||||||
scc_cstring_t *output);
|
}
|
||||||
cbool lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
|
||||||
usize *output);
|
|
||||||
cbool lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos,
|
|
||||||
scc_cstring_t *output);
|
|
||||||
void lex_parse_skip_endline(scc_probe_stream_t *input, scc_pos_t *pos);
|
|
||||||
void lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_pos_t *pos);
|
|
||||||
void lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos);
|
|
||||||
void lex_parse_skip_whitespace(scc_probe_stream_t *input, scc_pos_t *pos);
|
|
||||||
|
|
||||||
#endif /* __SMCC_LEX_PARSER_H__ */
|
int scc_lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos);
|
||||||
|
cbool scc_lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos,
|
||||||
|
scc_cstring_t *output);
|
||||||
|
cbool scc_lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
||||||
|
usize *output);
|
||||||
|
cbool scc_lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos,
|
||||||
|
scc_cstring_t *output);
|
||||||
|
void scc_lex_parse_skip_endline(scc_probe_stream_t *input, scc_pos_t *pos);
|
||||||
|
void scc_lex_parse_skip_block_comment(scc_probe_stream_t *input,
|
||||||
|
scc_pos_t *pos);
|
||||||
|
void scc_lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos);
|
||||||
|
void scc_lex_parse_skip_whitespace(scc_probe_stream_t *input, scc_pos_t *pos);
|
||||||
|
|
||||||
|
#endif /* __SCC_LEX_PARSER_H__ */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <lex_parser.h>
|
#include <lex_parser.h>
|
||||||
|
|
||||||
void 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);
|
||||||
@@ -57,20 +57,20 @@ static inline int got_simple_escape(int ch) {
|
|||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
}
|
}
|
||||||
|
|
||||||
void 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);
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO endline
|
// TODO endline
|
||||||
if (lex_parse_is_endline(ch)) {
|
if (scc_lex_parse_is_endline(ch)) {
|
||||||
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_consume(stream);
|
||||||
@@ -79,7 +79,8 @@ void lex_parse_skip_line(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_pos_t *pos) {
|
void scc_lex_parse_skip_block_comment(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);
|
||||||
int ch;
|
int ch;
|
||||||
@@ -97,13 +98,13 @@ void lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
scc_probe_stream_reset(stream);
|
scc_probe_stream_reset(stream);
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unterminated block comment");
|
LOG_WARN("Unterminated block comment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lex_parse_is_endline(ch)) {
|
if (scc_lex_parse_is_endline(ch)) {
|
||||||
lex_parse_skip_endline(stream, pos);
|
scc_lex_parse_skip_endline(stream, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
scc_probe_stream_consume(stream);
|
scc_probe_stream_consume(stream);
|
||||||
@@ -119,14 +120,14 @@ void lex_parse_skip_block_comment(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void 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);
|
||||||
|
|
||||||
if (!lex_parse_is_whitespace(ch)) {
|
if (!scc_lex_parse_is_whitespace(ch)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +150,7 @@ static inline cbool _lex_parse_uint(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
while (1) {
|
while (1) {
|
||||||
ch = scc_probe_stream_peek(input);
|
ch = scc_probe_stream_peek(input);
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
break;
|
break;
|
||||||
} else if (ch >= 'a' && ch <= 'z') {
|
} else if (ch >= 'a' && ch <= 'z') {
|
||||||
tmp = ch - 'a' + 10;
|
tmp = ch - 'a' + 10;
|
||||||
@@ -187,14 +188,14 @@ static inline cbool _lex_parse_uint(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
* @return int
|
* @return int
|
||||||
* https://cppreference.cn/w/c/language/character_constant
|
* https://cppreference.cn/w/c/language/character_constant
|
||||||
*/
|
*/
|
||||||
int 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);
|
scc_probe_stream_reset(stream);
|
||||||
int ch = scc_probe_stream_peek(stream);
|
int ch = scc_probe_stream_peek(stream);
|
||||||
int ret = core_stream_eof;
|
int ret = scc_stream_eof;
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unexpected EOF at begin");
|
LOG_WARN("Unexpected EOF at begin");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (ch != '\'') {
|
} else if (ch != '\'') {
|
||||||
@@ -207,7 +208,7 @@ int lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
ch = scc_probe_stream_consume(stream);
|
ch = scc_probe_stream_consume(stream);
|
||||||
scc_pos_next(pos);
|
scc_pos_next(pos);
|
||||||
|
|
||||||
if (ch == core_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 == '\\') {
|
||||||
@@ -245,7 +246,7 @@ int lex_parse_char(scc_probe_stream_t *input, scc_pos_t *pos) {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
ERR:
|
ERR:
|
||||||
return core_stream_eof;
|
return scc_stream_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,7 +258,7 @@ ERR:
|
|||||||
* @return cbool
|
* @return cbool
|
||||||
* https://cppreference.cn/w/c/language/string_literal
|
* https://cppreference.cn/w/c/language/string_literal
|
||||||
*/
|
*/
|
||||||
cbool lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos,
|
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);
|
||||||
@@ -265,7 +266,7 @@ cbool lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
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));
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unexpected EOF at begin");
|
LOG_WARN("Unexpected EOF at begin");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (ch != '"') {
|
} else if (ch != '"') {
|
||||||
@@ -279,10 +280,10 @@ cbool lex_parse_string(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
while (1) {
|
while (1) {
|
||||||
ch = scc_probe_stream_peek(stream);
|
ch = scc_probe_stream_peek(stream);
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_ERROR("Unexpected EOF at string literal");
|
LOG_ERROR("Unexpected EOF at string literal");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (lex_parse_is_endline(ch)) {
|
} else if (scc_lex_parse_is_endline(ch)) {
|
||||||
LOG_ERROR("Unexpected newline at string literal");
|
LOG_ERROR("Unexpected newline at string literal");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (ch == '\\') {
|
} else if (ch == '\\') {
|
||||||
@@ -323,7 +324,7 @@ ERR:
|
|||||||
* @return cbool
|
* @return cbool
|
||||||
* https://cppreference.cn/w/c/language/integer_constant
|
* https://cppreference.cn/w/c/language/integer_constant
|
||||||
*/
|
*/
|
||||||
cbool lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
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);
|
||||||
@@ -331,7 +332,7 @@ cbool lex_parse_number(scc_probe_stream_t *input, scc_pos_t *pos,
|
|||||||
int ch = scc_probe_stream_peek(stream);
|
int ch = scc_probe_stream_peek(stream);
|
||||||
int base = 10; // 默认十进制
|
int base = 10; // 默认十进制
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unexpected EOF at begin");
|
LOG_WARN("Unexpected EOF at begin");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
@@ -406,7 +407,7 @@ ERR:
|
|||||||
* @return cbool
|
* @return cbool
|
||||||
* https://cppreference.cn/w/c/language/identifier
|
* https://cppreference.cn/w/c/language/identifier
|
||||||
*/
|
*/
|
||||||
cbool lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos,
|
cbool scc_lex_parse_identifier(scc_probe_stream_t *input, scc_pos_t *pos,
|
||||||
scc_cstring_t *output) {
|
scc_cstring_t *output) {
|
||||||
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));
|
||||||
@@ -414,7 +415,7 @@ cbool lex_parse_identifier(scc_probe_stream_t *input, 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);
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LOG_WARN("Unexpected EOF at begin");
|
LOG_WARN("Unexpected EOF at begin");
|
||||||
} else if (ch == '_' || (ch >= 'a' && ch <= 'z') ||
|
} else if (ch == '_' || (ch >= 'a' && ch <= 'z') ||
|
||||||
(ch >= 'A' && ch <= 'Z')) {
|
(ch >= 'A' && ch <= 'Z')) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ cbool check_char(const char *str, int expect, int *output) {
|
|||||||
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 = lex_parse_char(stream, &pos);
|
*output = scc_lex_parse_char(stream, &pos);
|
||||||
return *output == expect;
|
return *output == expect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ cbool check_char(const char *str, int expect, int *output) {
|
|||||||
#define CHECK_CHAR_INVALID(str) \
|
#define CHECK_CHAR_INVALID(str) \
|
||||||
do { \
|
do { \
|
||||||
int _output; \
|
int _output; \
|
||||||
check_char(str, core_stream_eof, &_output); \
|
check_char(str, scc_stream_eof, &_output); \
|
||||||
TEST_CHECK(_output == core_stream_eof); \
|
TEST_CHECK(_output == scc_stream_eof); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void test_simple_char(void) {
|
void test_simple_char(void) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ cbool check_identifier(const char *str, const char *expect,
|
|||||||
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);
|
||||||
|
|
||||||
cbool ret = lex_parse_identifier(stream, &pos, output);
|
cbool ret = scc_lex_parse_identifier(stream, &pos, output);
|
||||||
if (ret && expect) {
|
if (ret && expect) {
|
||||||
return strcmp(output->data, expect) == 0;
|
return strcmp(output->data, expect) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ cbool check(const char *str, usize expect, usize *output) {
|
|||||||
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);
|
||||||
return lex_parse_number(stream, &pos, output);
|
return scc_lex_parse_number(stream, &pos, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_VALID(str, expect) \
|
#define CHECK_VALID(str, expect) \
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ void check_skip_block_comment(const char *str, const char *expect_remaining) {
|
|||||||
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);
|
||||||
|
|
||||||
lex_parse_skip_block_comment(stream, &pos);
|
scc_lex_parse_skip_block_comment(stream, &pos);
|
||||||
|
|
||||||
// Check remaining content
|
// Check remaining content
|
||||||
char buffer[256] = {0};
|
char buffer[256] = {0};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ch;
|
int ch;
|
||||||
while ((ch = scc_probe_stream_consume(stream)) != core_stream_eof &&
|
while ((ch = scc_probe_stream_consume(stream)) != scc_stream_eof &&
|
||||||
i < 255) {
|
i < 255) {
|
||||||
buffer[i++] = (char)ch;
|
buffer[i++] = (char)ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ void check_skip_line(const char *str, const char *expect_remaining) {
|
|||||||
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);
|
||||||
|
|
||||||
lex_parse_skip_line(stream, &pos);
|
scc_lex_parse_skip_line(stream, &pos);
|
||||||
|
|
||||||
// Check remaining content
|
// Check remaining content
|
||||||
char buffer[256] = {0};
|
char buffer[256] = {0};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ch;
|
int ch;
|
||||||
while ((ch = scc_probe_stream_consume(stream)) != core_stream_eof &&
|
while ((ch = scc_probe_stream_consume(stream)) != scc_stream_eof &&
|
||||||
i < 255) {
|
i < 255) {
|
||||||
buffer[i++] = (char)ch;
|
buffer[i++] = (char)ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ cbool check_string(const char *str, const char *expect, scc_cstring_t *output) {
|
|||||||
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);
|
||||||
|
|
||||||
cbool ret = lex_parse_string(stream, &pos, output);
|
cbool ret = scc_lex_parse_string(stream, &pos, output);
|
||||||
if (ret && expect) {
|
if (ret && expect) {
|
||||||
return strcmp(output->data, expect) == 0;
|
return strcmp(output->data, expect) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
#include "lexer_token.h"
|
#include "lexer_token.h"
|
||||||
#include <libcore.h>
|
#include <libcore.h>
|
||||||
|
|
||||||
typedef struct lexer_token {
|
typedef struct scc_lexer_token {
|
||||||
scc_tok_type_t type;
|
scc_tok_type_t type;
|
||||||
scc_cvalue_t value;
|
scc_cvalue_t value;
|
||||||
scc_pos_t loc;
|
scc_pos_t loc;
|
||||||
} lexer_tok_t;
|
} scc_lexer_tok_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 词法分析器核心结构体
|
* @brief 词法分析器核心结构体
|
||||||
@@ -39,7 +39,7 @@ void scc_lexer_init(scc_lexer_t *lexer, scc_probe_stream_t *stream);
|
|||||||
*
|
*
|
||||||
* 此函数会返回所有类型的token,包括空白符等无效token
|
* 此函数会返回所有类型的token,包括空白符等无效token
|
||||||
*/
|
*/
|
||||||
void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token);
|
void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取有效token
|
* @brief 获取有效token
|
||||||
@@ -48,6 +48,6 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token);
|
|||||||
*
|
*
|
||||||
* 此函数会自动跳过空白符等无效token,返回对语法分析有意义的token
|
* 此函数会自动跳过空白符等无效token,返回对语法分析有意义的token
|
||||||
*/
|
*/
|
||||||
void scc_lexer_get_valid_token(scc_lexer_t *lexer, lexer_tok_t *token);
|
void scc_lexer_get_valid_token(scc_lexer_t *lexer, scc_lexer_tok_t *token);
|
||||||
|
|
||||||
#endif /* __SCC_LEXER_H__ */
|
#endif /* __SCC_LEXER_H__ */
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void scc_lexer_init(scc_lexer_t *lexer, scc_probe_stream_t *stream) {
|
|||||||
|
|
||||||
#define set_err_token(token) ((token)->type = SCC_TOK_UNKNOWN)
|
#define set_err_token(token) ((token)->type = SCC_TOK_UNKNOWN)
|
||||||
|
|
||||||
static void parse_line(scc_lexer_t *lexer, lexer_tok_t *token) {
|
static void parse_line(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
||||||
token->loc = lexer->pos;
|
token->loc = lexer->pos;
|
||||||
scc_probe_stream_t *stream = lexer->stream;
|
scc_probe_stream_t *stream = lexer->stream;
|
||||||
scc_probe_stream_reset(stream);
|
scc_probe_stream_reset(stream);
|
||||||
@@ -93,7 +93,7 @@ static void parse_line(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
usize n;
|
usize n;
|
||||||
scc_cstring_t str = scc_cstring_new();
|
scc_cstring_t str = scc_cstring_new();
|
||||||
|
|
||||||
if (ch == core_stream_eof) {
|
if (ch == scc_stream_eof) {
|
||||||
LEX_WARN("Unexpected EOF at begin");
|
LEX_WARN("Unexpected EOF at begin");
|
||||||
goto ERR;
|
goto ERR;
|
||||||
} else if (ch != '#') {
|
} else if (ch != '#') {
|
||||||
@@ -113,13 +113,13 @@ static void parse_line(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lex_parse_number(lexer->stream, &lexer->pos, &n) == false) {
|
if (scc_lex_parse_number(lexer->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) != ' ') {
|
||||||
lex_parse_skip_line(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_line(lexer->stream, &lexer->pos);
|
||||||
token->loc.line = token->value.n;
|
token->loc.line = token->value.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,26 +127,26 @@ static void parse_line(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
LEX_ERROR("Invalid `#` line");
|
LEX_ERROR("Invalid `#` line");
|
||||||
goto SKIP_LINE;
|
goto SKIP_LINE;
|
||||||
}
|
}
|
||||||
if (lex_parse_string(lexer->stream, &lexer->pos, &str) == false) {
|
if (scc_lex_parse_string(lexer->stream, &lexer->pos, &str) == false) {
|
||||||
LEX_ERROR("Invalid filename");
|
LEX_ERROR("Invalid filename");
|
||||||
goto SKIP_LINE;
|
goto SKIP_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
lex_parse_skip_line(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_line(lexer->stream, &lexer->pos);
|
||||||
token->loc.line = n;
|
token->loc.line = n;
|
||||||
// FIXME memory leak
|
// FIXME memory leak
|
||||||
token->loc.name = scc_cstring_from_cstr(scc_cstring_as_cstr(&str));
|
token->loc.name = scc_cstring_from_cstr(scc_cstring_as_cstr(&str));
|
||||||
scc_cstring_free(&str);
|
scc_cstring_free(&str);
|
||||||
return;
|
return;
|
||||||
SKIP_LINE:
|
SKIP_LINE:
|
||||||
lex_parse_skip_line(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_line(lexer->stream, &lexer->pos);
|
||||||
ERR:
|
ERR:
|
||||||
set_err_token(token);
|
set_err_token(token);
|
||||||
scc_cstring_free(&str);
|
scc_cstring_free(&str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /zh/c/language/operator_arithmetic.html
|
// /zh/c/language/operator_arithmetic.html
|
||||||
void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
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_UNKNOWN;
|
token->type = SCC_TOK_UNKNOWN;
|
||||||
scc_probe_stream_t *stream = lexer->stream;
|
scc_probe_stream_t *stream = lexer->stream;
|
||||||
@@ -212,11 +212,11 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
type = SCC_TOK_ASSIGN_DIV;
|
type = SCC_TOK_ASSIGN_DIV;
|
||||||
goto double_char;
|
goto double_char;
|
||||||
case '/':
|
case '/':
|
||||||
lex_parse_skip_line(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_line(lexer->stream, &lexer->pos);
|
||||||
token->type = SCC_TOK_LINE_COMMENT;
|
token->type = SCC_TOK_LINE_COMMENT;
|
||||||
goto END;
|
goto END;
|
||||||
case '*':
|
case '*':
|
||||||
lex_parse_skip_block_comment(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_block_comment(lexer->stream, &lexer->pos);
|
||||||
token->type = SCC_TOK_BLOCK_COMMENT;
|
token->type = SCC_TOK_BLOCK_COMMENT;
|
||||||
goto END;
|
goto END;
|
||||||
default:
|
default:
|
||||||
@@ -369,7 +369,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\n':
|
case '\n':
|
||||||
lex_parse_skip_endline(lexer->stream, &lexer->pos);
|
scc_lex_parse_skip_endline(lexer->stream, &lexer->pos);
|
||||||
token->type = SCC_TOK_BLANK;
|
token->type = SCC_TOK_BLANK;
|
||||||
goto END;
|
goto END;
|
||||||
case '#':
|
case '#':
|
||||||
@@ -377,15 +377,15 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
token->type = SCC_TOK_BLANK;
|
token->type = SCC_TOK_BLANK;
|
||||||
goto END;
|
goto END;
|
||||||
case '\0':
|
case '\0':
|
||||||
case core_stream_eof:
|
case scc_stream_eof:
|
||||||
// EOF
|
// EOF
|
||||||
type = SCC_TOK_EOF;
|
type = SCC_TOK_EOF;
|
||||||
break;
|
break;
|
||||||
case '\'': {
|
case '\'': {
|
||||||
token->loc = lexer->pos;
|
token->loc = lexer->pos;
|
||||||
token->type = SCC_TOK_CHAR_LITERAL;
|
token->type = SCC_TOK_CHAR_LITERAL;
|
||||||
int ch = lex_parse_char(lexer->stream, &lexer->pos);
|
int ch = scc_lex_parse_char(lexer->stream, &lexer->pos);
|
||||||
if (ch == core_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;
|
||||||
} else {
|
} else {
|
||||||
@@ -397,7 +397,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
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_new();
|
||||||
if (lex_parse_string(lexer->stream, &lexer->pos, &output) == true) {
|
if (scc_lex_parse_string(lexer->stream, &lexer->pos, &output) == true) {
|
||||||
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 +414,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, 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 (lex_parse_number(lexer->stream, &lexer->pos, &output) == true) {
|
if (scc_lex_parse_number(lexer->stream, &lexer->pos, &output) == true) {
|
||||||
token->value.n = output;
|
token->value.n = output;
|
||||||
} else {
|
} else {
|
||||||
LEX_ERROR("Unexpected number literal");
|
LEX_ERROR("Unexpected number literal");
|
||||||
@@ -432,7 +432,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
|||||||
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_new();
|
||||||
cbool ret = lex_parse_identifier(lexer->stream, &lexer->pos, &str);
|
cbool ret = scc_lex_parse_identifier(lexer->stream, &lexer->pos, &str);
|
||||||
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));
|
||||||
@@ -467,7 +467,7 @@ END:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scc_lexer_get_token maybe got invalid (with parser)
|
// scc_lexer_get_token maybe got invalid (with parser)
|
||||||
void scc_lexer_get_valid_token(scc_lexer_t *lexer, lexer_tok_t *token) {
|
void scc_lexer_get_valid_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
||||||
scc_tok_subtype_t type;
|
scc_tok_subtype_t type;
|
||||||
do {
|
do {
|
||||||
scc_lexer_get_token(lexer, token);
|
scc_lexer_get_token(lexer, token);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
static inline void test_lexer_string(const char *input,
|
static inline void test_lexer_string(const char *input,
|
||||||
scc_tok_type_t expected_type) {
|
scc_tok_type_t expected_type) {
|
||||||
scc_lexer_t lexer;
|
scc_lexer_t lexer;
|
||||||
lexer_tok_t token;
|
scc_lexer_tok_t token;
|
||||||
scc_mem_probe_stream_t stream;
|
scc_mem_probe_stream_t stream;
|
||||||
|
|
||||||
scc_lexer_init(&lexer, scc_mem_probe_stream_init(&stream, input,
|
scc_lexer_init(&lexer, scc_mem_probe_stream_init(&stream, input,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ int main(int argc, char *argv[]) {
|
|||||||
scc_cstring_clear(&stream->name);
|
scc_cstring_clear(&stream->name);
|
||||||
scc_cstring_append_cstr(&stream->name, file_name, strlen(file_name));
|
scc_cstring_append_cstr(&stream->name, file_name, strlen(file_name));
|
||||||
scc_lexer_init(&lexer, stream);
|
scc_lexer_init(&lexer, stream);
|
||||||
lexer_tok_t tok;
|
scc_lexer_tok_t tok;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
scc_lexer_get_valid_token(&lexer, &tok);
|
scc_lexer_get_valid_token(&lexer, &tok);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
struct scc_probe_stream;
|
struct scc_probe_stream;
|
||||||
typedef struct scc_probe_stream scc_probe_stream_t;
|
typedef struct scc_probe_stream scc_probe_stream_t;
|
||||||
|
|
||||||
#define core_stream_eof (-1)
|
#define scc_stream_eof (-1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 带探针的流接口
|
* @brief 带探针的流接口
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ static int mem_probe_stream_consume(scc_probe_stream_t *_stream) {
|
|||||||
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
||||||
|
|
||||||
if (stream->curr_pos >= stream->data_length) {
|
if (stream->curr_pos >= stream->data_length) {
|
||||||
return core_stream_eof;
|
return scc_stream_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char ch = stream->data[stream->curr_pos++];
|
unsigned char ch = stream->data[stream->curr_pos++];
|
||||||
@@ -24,7 +24,7 @@ static int mem_probe_stream_peek(scc_probe_stream_t *_stream) {
|
|||||||
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
||||||
|
|
||||||
if (stream->probe_pos >= stream->data_length) {
|
if (stream->probe_pos >= stream->data_length) {
|
||||||
return core_stream_eof;
|
return scc_stream_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只查看而不移动探针位置
|
// 只查看而不移动探针位置
|
||||||
@@ -36,7 +36,7 @@ static int mem_probe_stream_next(scc_probe_stream_t *_stream) {
|
|||||||
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
|
||||||
|
|
||||||
if (stream->probe_pos >= stream->data_length) {
|
if (stream->probe_pos >= stream->data_length) {
|
||||||
return core_stream_eof;
|
return scc_stream_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回探针位置的字符,并将探针位置向前移动
|
// 返回探针位置的字符,并将探针位置向前移动
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* @enum hp_entry_state_t
|
* @enum hp_entry_state_t
|
||||||
* @brief 哈希表条目状态标识
|
* @brief 哈希表条目状态标识
|
||||||
*/
|
*/
|
||||||
typedef enum scc_hashmap_entry_state {
|
typedef enum scc_hashtable_entry_state {
|
||||||
ENTRY_EMPTY, /**< 空槽位(从未使用过) */
|
ENTRY_EMPTY, /**< 空槽位(从未使用过) */
|
||||||
ENTRY_ACTIVE, /**< 有效条目(包含键值对) */
|
ENTRY_ACTIVE, /**< 有效条目(包含键值对) */
|
||||||
ENTRY_TOMBSTONE /**< 墓碑标记(已删除条目) */
|
ENTRY_TOMBSTONE /**< 墓碑标记(已删除条目) */
|
||||||
@@ -118,7 +118,7 @@ typedef int (*scc_hashtable_iter_fn)(const void *key, void *value,
|
|||||||
* @param iter_func 迭代回调函数
|
* @param iter_func 迭代回调函数
|
||||||
* @param context 用户上下文指针
|
* @param context 用户上下文指针
|
||||||
*/
|
*/
|
||||||
void scc_hashmap_foreach(scc_hashtable_t *ht, scc_hashtable_iter_fn iter_func,
|
void scc_hashtable_foreach(scc_hashtable_t *ht, scc_hashtable_iter_fn iter_func,
|
||||||
void *context);
|
void *context);
|
||||||
|
|
||||||
#endif /* __SCC_HASHMAP_H__ */
|
#endif /* __SCC_HASHMAP_H__ */
|
||||||
|
|||||||
@@ -142,12 +142,12 @@ void scc_hashtable_drop(scc_hashtable_t *ht) {
|
|||||||
ht->tombstone_count = 0;
|
ht->tombstone_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_hashmap_foreach(scc_hashtable_t *ht, scc_hashtable_iter_fn iter_func,
|
void scc_hashtable_foreach(scc_hashtable_t *ht, scc_hashtable_iter_fn iter_func,
|
||||||
void *context) {
|
void *context) {
|
||||||
for (usize i = 0; i < ht->entries.cap; i++) {
|
for (usize i = 0; i < ht->entries.cap; i++) {
|
||||||
scc_hashtable_entry_t *entry = &scc_vec_at(ht->entries, i);
|
scc_hashtable_entry_t *entry = &scc_vec_at(ht->entries, i);
|
||||||
if (entry->state == ENTRY_ACTIVE) {
|
if (entry->state == ENTRY_ACTIVE) {
|
||||||
if (!iter_func(entry->key, entry->value, context)) {
|
if (iter_func(entry->key, entry->value, context)) {
|
||||||
break; // enable callback function terminal the iter
|
break; // enable callback function terminal the iter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ void scc_strpool_drop(scc_strpool_t *pool) { scc_hashtable_drop(&pool->ht); }
|
|||||||
|
|
||||||
void scc_strpool_foreach(scc_strpool_t *pool, scc_strpool_iter_fn iter_func,
|
void scc_strpool_foreach(scc_strpool_t *pool, scc_strpool_iter_fn iter_func,
|
||||||
void *context) {
|
void *context) {
|
||||||
scc_hashmap_foreach(&pool->ht, (scc_hashtable_iter_fn)iter_func, context);
|
scc_hashtable_foreach(&pool->ht, (scc_hashtable_iter_fn)iter_func, context);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user