#include "../parser.h" #include "../symtab/symtab.h" #include "ast.h" #ifndef FUNC_PARAM_CACHE_SIZE #define FUNC_PARAM_CACHE_SIZE 32 // 合理初始值,可覆盖99%常见情况 #endif struct FuncParamCache { struct Token tokens[FUNC_PARAM_CACHE_SIZE]; int read_pos; // 当前读取位置 int write_pos; // 写入位置 int depth; // 当前缓存深度 }; static enum TokenType peekcachetype(struct FuncParamCache* cache) { return cache->tokens[cache->read_pos++].type; } // TODO 语义分析压入符号表 static void parse_params(struct Parser* parser, struct FuncParamCache* cache, struct ASTNode* node) { // = peekcachetype(cache); enum TokenType ttype; // if (ttype != TOKEN_L_PAREN) { // error("function expected '('\n"); // } struct ASTNode *params = new_ast_node(); node->func.params = params; int params_size = 0; while ((ttype = peekcachetype(cache)) != TOKEN_R_PAREN) { switch (ttype) { case TOKEN_COMMA: break; case TOKEN_ELLIPSIS: ttype = peekcachetype(cache); if (ttype != TOKEN_R_PAREN) { error("... must be a last parameter list (expect ')')"); } // TODO error("not implement"); break; case TOKEN_IDENT: params->children[params_size++] = NULL; break; default: // TODO 使用cache的类型解析 // parse_type(parser); // TODO type parse // ttype = peekcachetype(cache); // ttype = peekcachetype(cache); // if (ttype != TOKEN_IDENT) { // node->node_type = NT_DECL_FUNC; // flushpeektok(parser); // continue; // } // error("function expected ')' or ','\n"); } } } enum ASTType check_is_func_decl(struct Parser* parser, struct FuncParamCache* cache) { cache->depth = 1; cache->read_pos = 0; cache->write_pos = 0; while (cache->depth) { struct Token* tok = peektok(parser); poptok(parser); if (cache->write_pos >= FUNC_PARAM_CACHE_SIZE - 1) { error("function parameter list too long"); } cache->tokens[cache->write_pos++] = *tok; switch (tok->type) { case TOKEN_L_PAREN: cache->depth++; break; case TOKEN_R_PAREN: cache->depth--; break; } } switch (peektoktype(parser)) { case TOKEN_SEMICOLON: poptok(parser); return NT_DECL_FUNC; case TOKEN_L_BRACE: return NT_FUNC; break; default: error("function define or decl need '{' or ';' but you don't got"); } } struct ASTNode* parse_func(struct Parser* parser) { struct ASTNode* ret_type = parse_type(parser); struct ASTNode* func_name = parse_ident(parser); struct ASTNode* node = new_ast_node(); node->func.ret = ret_type; node->func.name = func_name; flushpeektok(parser); expecttok(parser, TOKEN_L_PAREN); struct FuncParamCache cache; node->type = check_is_func_decl(parser, &cache); symtab_add_symbol(parser->symtab, func_name->syms.tok.constant.str, node); if (node->type == NT_DECL_FUNC) { return node; } symtab_enter_scope(parser->symtab); parse_params(parser, &cache, node); node->func.body = parse_block(parser); symtab_leave_scope(parser->symtab); return node; }