- 重命名和重构了多个文件,包括 lexer、parser 和 AST 相关代码 - 添加了日志功能,使用 LOG_* 宏替代原有的 error 和 warn 函数 - 优化了错误处理和内存分配方式 - 调整了代码结构,提高了模块化和可读性
170 lines
5.0 KiB
C
170 lines
5.0 KiB
C
#include "../ast.h"
|
||
#include "../parser.h"
|
||
#include "../symtab/symtab.h"
|
||
|
||
#ifndef FUNC_PARAM_CACHE_SIZE
|
||
#define FUNC_PARAM_CACHE_SIZE 32 // 合理初始值,可覆盖99%常见情况
|
||
#endif
|
||
|
||
// TODO 语义分析压入符号表
|
||
static void parse_params(parser_t* parser, tok_stream_t* cache, ast_node_t* node) {
|
||
flush_peek_tok(cache);
|
||
tok_type_t ttype;
|
||
ast_node_t *params = new_ast_node();
|
||
node->decl_func.params = params;
|
||
vector_init(params->params.params);
|
||
|
||
int depth = 1;
|
||
while (depth) {
|
||
ttype = peek_tok_type(cache);
|
||
switch (ttype) {
|
||
case TOKEN_COMMA:
|
||
break;
|
||
case TOKEN_ELLIPSIS:
|
||
ttype = peek_tok_type(cache);
|
||
if (ttype != TOKEN_R_PAREN) {
|
||
LOG_ERROR("... must be a last parameter list (expect ')')");
|
||
}
|
||
// TODO
|
||
LOG_ERROR("not implement");
|
||
break;
|
||
case TOKEN_IDENT:
|
||
// TODO 静态数组
|
||
flush_peek_tok(cache);
|
||
ast_node_t* id_node = new_ast_ident_node(peek_tok(cache));
|
||
ast_node_t* node = new_ast_node();
|
||
node->type = NT_DECL_VAR;
|
||
node->decl_val.name = id_node;
|
||
// TODO typing sys
|
||
node->decl_val.type = NULL;
|
||
node->decl_val.expr_stmt = NULL;
|
||
node->decl_val.data = NULL;
|
||
vector_push(params->params.params, node);
|
||
symtab_add_symbol(parser->symtab, id_node->syms.tok.val.str, node, 0);
|
||
break;
|
||
case TOKEN_L_PAREN: {
|
||
depth++;
|
||
break;
|
||
}
|
||
case TOKEN_R_PAREN: {
|
||
depth--;
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
// TODO 使用cache的类型解析
|
||
// parse_type(parser);
|
||
// TODO type parse
|
||
// ttype = peekcachetype(cache);
|
||
// ttype = peekcachetype(cache);
|
||
// if (ttype != TOKEN_IDENT) {
|
||
// node->node_type = NT_DECL_FUNC;
|
||
// flush_peek_tok(tokbuf);
|
||
// continue;
|
||
// }
|
||
// LOG_ERROR("function expected ')' or ','\n");
|
||
}
|
||
pop_tok(cache);
|
||
}
|
||
}
|
||
|
||
ast_type_t check_is_func_decl(tok_stream_t* tokbuf, tok_stream_t* cache) {
|
||
expect_pop_tok(tokbuf, TOKEN_L_PAREN);
|
||
int depth = 1;
|
||
|
||
while (depth) {
|
||
tok_t* tok = peek_tok(tokbuf);
|
||
pop_tok(tokbuf);
|
||
if (cache->size >= cache->cap - 1) {
|
||
LOG_ERROR("function parameter list too long");
|
||
}
|
||
cache->buf[cache->size++] = *tok;
|
||
switch (tok->type) {
|
||
case TOKEN_L_PAREN:
|
||
depth++;
|
||
break;
|
||
case TOKEN_R_PAREN:
|
||
depth--;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
cache->end = cache->size;
|
||
|
||
switch (peek_tok_type(tokbuf)) {
|
||
case TOKEN_SEMICOLON:
|
||
pop_tok(tokbuf);
|
||
return NT_DECL_FUNC;
|
||
case TOKEN_L_BRACE:
|
||
return NT_FUNC;
|
||
break;
|
||
default:
|
||
LOG_ERROR("function define or decl need '{' or ';' but you don't got");
|
||
}
|
||
}
|
||
|
||
static ast_node_t* new_ast_node_funcdecl(ast_node_t* ret, ast_node_t* name) {
|
||
ast_node_t* node = new_ast_node();
|
||
node->type = NT_DECL_FUNC;
|
||
node->decl_func.ret = ret;
|
||
node->decl_func.name = name;
|
||
node->decl_func.def = NULL;
|
||
return node;
|
||
}
|
||
|
||
void parse_func(parser_t* parser) {
|
||
tok_stream_t* tokbuf = &(parser->tokbuf);
|
||
flush_peek_tok(tokbuf);
|
||
ast_node_t* ret_node = parse_type(parser);
|
||
ast_node_t* name_node = expect_pop_ident(tokbuf);
|
||
const char* func_name = name_node->syms.tok.val.str;
|
||
ast_node_t* decl = new_ast_node_funcdecl(ret_node, name_node);
|
||
|
||
tok_stream_t cache;
|
||
init_tokbuf(&cache, NULL, NULL);
|
||
cache.cap = FUNC_PARAM_CACHE_SIZE;
|
||
tok_t buf[FUNC_PARAM_CACHE_SIZE];
|
||
cache.buf = buf;
|
||
|
||
ast_type_t type = check_is_func_decl(&(parser->tokbuf), &cache);
|
||
|
||
ast_node_t* prev = symtab_add_symbol(parser->symtab, func_name, decl, 1);
|
||
if (prev != NULL) {
|
||
if (prev->type != NT_DECL_FUNC) {
|
||
LOG_ERROR("the symbol duplicate old is %d, new is func", prev->type);
|
||
}
|
||
// TODO check redeclare func is match
|
||
if (type == NT_FUNC) {
|
||
// TODO Free decl;
|
||
rt._free(decl);
|
||
decl = prev;
|
||
goto FUNC;
|
||
}
|
||
return;
|
||
}
|
||
vector_push(parser->root->root.children, decl);
|
||
if (type == NT_DECL_FUNC) {
|
||
return;
|
||
}
|
||
|
||
FUNC:
|
||
// 该data临时用于判断是否重复定义
|
||
if (decl->decl_func.def != NULL) {
|
||
LOG_ERROR("redefinition of function %s", func_name);
|
||
}
|
||
|
||
ast_node_t* node = new_ast_node();
|
||
node->type = NT_FUNC;
|
||
node->func.decl = decl;
|
||
node->func.data = NULL;
|
||
|
||
decl->decl_func.def = node;
|
||
symtab_enter_scope(parser->symtab);
|
||
parse_params(parser, &cache, decl);
|
||
node->func.body = parse_block(parser);
|
||
symtab_leave_scope(parser->symtab);
|
||
|
||
vector_push(parser->root->root.children, node);
|
||
}
|