- 重命名和重构了多个文件,包括 lexer、parser 和 AST 相关代码 - 添加了日志功能,使用 LOG_* 宏替代原有的 error 和 warn 函数 - 优化了错误处理和内存分配方式 - 调整了代码结构,提高了模块化和可读性
87 lines
2.1 KiB
C
87 lines
2.1 KiB
C
#include <lib/core.h>
|
||
#include "lexer_log.h"
|
||
#include "token.h"
|
||
|
||
#define ROUND_IDX(idx) ((idx) % tokbuf->cap)
|
||
|
||
tok_t* pop_tok(tok_stream_t* tokbuf) {
|
||
if (tokbuf->size == 0) {
|
||
LEX_ERROR("no token to pop");
|
||
return NULL;
|
||
}
|
||
int idx = tokbuf->cur;
|
||
tokbuf->cur = ROUND_IDX(idx + 1);
|
||
tokbuf->size -= 1;
|
||
return tokbuf->buf + idx;
|
||
}
|
||
|
||
void flush_peek_tok(tok_stream_t* tokbuf) {
|
||
tokbuf->peek = tokbuf->cur;
|
||
}
|
||
|
||
void init_tokbuf(tok_stream_t *tokbuf, void *stream, tok_stream_get_func gettok) {
|
||
tokbuf->cur = 0;
|
||
tokbuf->end = 0;
|
||
tokbuf->peek = 0;
|
||
tokbuf->size = 0;
|
||
tokbuf->stream = stream;
|
||
tokbuf->gettok = gettok;
|
||
tokbuf->buf = NULL;
|
||
tokbuf->cap = 0;
|
||
}
|
||
|
||
tok_t *peek_tok(tok_stream_t *tokbuf) {
|
||
Assert(tokbuf->size <= tokbuf->cap);
|
||
int idx = tokbuf->peek;
|
||
tokbuf->peek = ROUND_IDX(idx + 1);
|
||
|
||
if (idx == tokbuf->end) {
|
||
if (tokbuf->size == tokbuf->cap) {
|
||
LEX_ERROR("peek_tok buffer overflow");
|
||
return NULL;
|
||
}
|
||
if (tokbuf->gettok == NULL) {
|
||
LEX_ERROR("peek_tok can not got tok");
|
||
return NULL;
|
||
}
|
||
tokbuf->gettok(tokbuf->stream, &(tokbuf->buf[idx]));
|
||
tokbuf->size++;
|
||
tokbuf->end = tokbuf->peek;
|
||
}
|
||
|
||
return &(tokbuf->buf[idx]);
|
||
}
|
||
|
||
tok_type_t peek_tok_type(tok_stream_t* tokbuf) {
|
||
return peek_tok(tokbuf)->type;
|
||
}
|
||
|
||
int expect_pop_tok(tok_stream_t* tokbuf, tok_type_t type) {
|
||
flush_peek_tok(tokbuf);
|
||
tok_t* tok = peek_tok(tokbuf);
|
||
if (tok->type != type) {
|
||
LEX_ERROR("expected tok `%s` but got `%s`", get_tok_name(type), get_tok_name(tok->type));
|
||
return 0;
|
||
} else {
|
||
pop_tok(tokbuf);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 生成字符串映射(根据需求选择#str或#name)
|
||
static const char* token_strings[] = {
|
||
// 普通token使用#str
|
||
#define X(str, tok) [tok] = #str,
|
||
TOKEN_TABLE
|
||
#undef X
|
||
|
||
// 关键字使用#name
|
||
#define X(name, std, tok) [tok] = #name,
|
||
KEYWORD_TABLE
|
||
#undef X
|
||
};
|
||
|
||
const char* get_tok_name(tok_type_t type) {
|
||
return token_strings[type];
|
||
}
|