87 lines
2.0 KiB
C
87 lines
2.0 KiB
C
#define FRONTEND_IMPLEMENTATION
|
||
#include "../frontend.h"
|
||
#include "token.h"
|
||
|
||
#define ROUND_IDX(idx) ((idx) % tokbuf->cap)
|
||
|
||
tok_t* pop_tok(tok_buf_t* tokbuf) {
|
||
if (tokbuf->size == 0) {
|
||
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_buf_t* tokbuf) {
|
||
tokbuf->peek = tokbuf->cur;
|
||
}
|
||
|
||
void init_tokbuf(tok_buf_t *tokbuf, void *stream, get_tokbuf_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_buf_t *tokbuf)
|
||
{
|
||
int idx = tokbuf->peek;
|
||
idx = ROUND_IDX(idx + 1);
|
||
if (tokbuf->size >= tokbuf->cap) {
|
||
error("peek too deep, outof array size");
|
||
}
|
||
if (tokbuf->peek == tokbuf->end) {
|
||
if (tokbuf->size == tokbuf->cap) {
|
||
error("peek_tok buffer overflow");
|
||
}
|
||
if (tokbuf->gettok == NULL) {
|
||
error("peek_tok can not got tok");
|
||
}
|
||
tokbuf->gettok(tokbuf->stream, &(tokbuf->buf[idx]));
|
||
tokbuf->size++;
|
||
tokbuf->end = idx;
|
||
}
|
||
|
||
tokbuf->peek = idx;
|
||
return &(tokbuf->buf[idx]);
|
||
}
|
||
|
||
tok_type_t peek_tok_type(tok_buf_t* tokbuf) {
|
||
return peek_tok(tokbuf)->type;
|
||
}
|
||
|
||
int expect_pop_tok(tok_buf_t* tokbuf, tok_type_t type) {
|
||
flush_peek_tok(tokbuf);
|
||
tok_t* tok = peek_tok(tokbuf);
|
||
if (tok->type != type) {
|
||
error("expected tok: %s, got %s", get_tok_name(type), get_tok_name(tok->type));
|
||
} 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];
|
||
}
|