feat(parser): 实现赋值表达式和常量表达式解析功能
- 添加 scc_parse_assignment_expression 函数用于解析赋值表达式 - 添加 scc_parser_constant_expression 函数用于解析常量表达式 - 修改 cast 表达式解析逻辑,修复类型转换解析问题 - 改进错误处理机制,使用 SCC_ERROR 替代 LOG_ERROR 并提供准确位置信息 - 移除未使用的变量声明,优化代码结构 refactor(ast): 调整类型定义中的 typedef 类型存储结构 - 将 scc_ast_type 中的 underlying 字段改为 decl 字段 - 更新相关初始化函数以适配新的字段名称 - 修复枚举类型初始化时缺失的 decl 字段设置 feat(ast): 添加类型转换、sizeof 和 alignof 表达式的初始化函数 - 实现 scc_ast_expr_cast_init 用于初始化类型转换表达式 - 实现 scc_ast_expr_sizeof_init 用于初始化 sizeof 表达式 - 实现 scc_ast_expr_alignof_init 用于初始化 alignof 表达式 - 完善表达式类型的支持 chore(parser): 增加语义分析回调接口和位置获取工具函数 - 添加 scc_parse_decl_sema、scc_parse_type_sema 等语义分析辅助函数 - 提供 scc_parser_got_current_pos 函数获取当前解析位置 - 增强错误报告的准确性 refactor(dump): 完善 AST 转储功能,支持 break 和 continue 语句 - 为 SCC_AST_STMT_BREAK 和 SCC_AST_STMT_CONTINUE 添加转储支持 - 优化转储函数的分支处理结构
This commit is contained in:
@@ -155,9 +155,6 @@ A.2.4 External definitions
|
||||
#include <scc_parser.h>
|
||||
|
||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
cbool ok;
|
||||
scc_lexer_tok_t tok;
|
||||
|
||||
scc_ast_node_t *type_or_decl = _scc_parse_type(parser);
|
||||
scc_ast_decl_t *decl = null;
|
||||
if (type_or_decl == null) {
|
||||
@@ -182,7 +179,7 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
} else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) {
|
||||
decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
|
||||
} else {
|
||||
LOG_ERROR("invalid declaration");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -195,7 +192,7 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *init = scc_parse_expression(parser);
|
||||
decl->var.init = init;
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("expect semicolon");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon");
|
||||
}
|
||||
goto RETURN;
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
@@ -211,9 +208,6 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
RETURN:
|
||||
if (decl) {
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
decl->base.type, decl);
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -167,8 +167,6 @@ static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser);
|
||||
|
||||
// 特殊结构:独立解析(右结合、条件、一元、后缀、基本)
|
||||
static scc_ast_expr_t *
|
||||
parse_assignment_expression(scc_parser_t *parser); // 右结合
|
||||
static scc_ast_expr_t *
|
||||
parse_conditional_expression(scc_parser_t *parser); // 右结合
|
||||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser); // 类型转换
|
||||
static scc_ast_expr_t *
|
||||
@@ -520,7 +518,7 @@ static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
// 赋值表达式(右结合)
|
||||
static scc_ast_expr_t *parse_assignment_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||||
// unary-expression)
|
||||
scc_ast_expr_t *left = null;
|
||||
@@ -542,7 +540,7 @@ static scc_ast_expr_t *parse_assignment_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
|
||||
// 解析右侧(右结合:继续调用 parse_assignment_expression)
|
||||
scc_ast_expr_t *right = parse_assignment_expression(parser);
|
||||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||||
if (!right) {
|
||||
// 错误恢复
|
||||
parser_sync(parser);
|
||||
@@ -577,7 +575,8 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
|
||||
// 消耗 ':'
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
LOG_ERROR("Expected ':' after '?'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ':' after '?'");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
@@ -600,6 +599,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
if (tok && tok->type == SCC_TOK_L_PAREN) {
|
||||
// 尝试解析类型名
|
||||
scc_parser_store(parser);
|
||||
scc_parser_next(parser);
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现
|
||||
if (type) {
|
||||
// 消耗了类型名后,下一个应该是 ')'
|
||||
@@ -618,13 +618,12 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
return expr;
|
||||
} else {
|
||||
// 不是类型转换,回退
|
||||
scc_parser_restore(parser);
|
||||
// 释放 type(假设 scc_parse_type_name 分配了)
|
||||
// TODO: scc_ast_type_drop(type);
|
||||
}
|
||||
} else {
|
||||
// 解析类型名失败,回退
|
||||
scc_parser_restore(parser);
|
||||
// 解析类型名失败,回退
|
||||
}
|
||||
}
|
||||
// 否则作为一元表达式
|
||||
@@ -679,7 +678,8 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
|
||||
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
||||
if (!next) {
|
||||
LOG_ERROR("Unexpected end after sizeof");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected end after sizeof");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -741,7 +741,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||
LOG_ERROR("Expected ']' after subscript");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ']' after subscript");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
@@ -766,7 +767,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
// 解析参数列表
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
while (1) {
|
||||
scc_ast_expr_t *arg = parse_assignment_expression(parser);
|
||||
scc_ast_expr_t *arg =
|
||||
scc_parse_assignment_expression(parser);
|
||||
if (!arg) {
|
||||
parser_sync(parser);
|
||||
// 释放已解析的参数
|
||||
@@ -781,7 +783,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
break;
|
||||
} else {
|
||||
LOG_ERROR("Expected ',' or ')' in function call");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ',' or ')' in function call");
|
||||
parser_sync(parser);
|
||||
// 释放资源
|
||||
scc_free(call);
|
||||
@@ -800,12 +803,14 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_t ident_tok;
|
||||
if (!scc_parser_next_consume(parser, &ident_tok) ||
|
||||
ident_tok.type != SCC_TOK_IDENT) {
|
||||
LOG_ERROR("Expected identifier after member access");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected identifier after member access");
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
|
||||
|
||||
scc_ast_expr_t *member = expr_create(
|
||||
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
|
||||
: SCC_AST_EXPR_PTR_MEMBER);
|
||||
@@ -944,7 +949,8 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("Expected ')' after expression");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ')' after expression");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
@@ -952,12 +958,12 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *left = parse_assignment_expression(parser);
|
||||
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
||||
if (!left)
|
||||
return null;
|
||||
|
||||
while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
scc_ast_expr_t *right = parse_assignment_expression(parser);
|
||||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||||
if (!right) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
@@ -966,3 +972,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
|
||||
return parse_conditional_expression(parser);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ A.2.3 Statements
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
static inline scc_ast_stmt_t *ast_stmt_alloc() {
|
||||
scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t));
|
||||
if (stmt == null) {
|
||||
@@ -59,13 +60,15 @@ static inline scc_ast_stmt_t *ast_stmt_alloc() {
|
||||
|
||||
static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
LOG_ERROR("Expected '(' before like `( expression )` .");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected '(' before like `( expression )` .");
|
||||
}
|
||||
|
||||
scc_ast_expr_t *ret = scc_parse_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("Expected ')' before like `( expression )` .");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ')' before like `( expression )` .");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -97,10 +100,16 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = null;
|
||||
// TODO = scc_parser_constant_expression();
|
||||
expr = scc_parser_constant_expression(parser);
|
||||
if (expr == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected constant expression after case.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
LOG_ERROR("Expected constant expression after case.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected `:` after case.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -120,7 +129,8 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
LOG_ERROR("Expected constant expression after case.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected constant expression after case.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -150,7 +160,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
ret = (scc_ast_node_t *)scc_parse_statement(parser);
|
||||
}
|
||||
if (ret == null) {
|
||||
LOG_ERROR("Invalid statement");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Invalid statement");
|
||||
// TODO free
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
@@ -217,7 +227,8 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||
LOG_ERROR("Expected 'while' after do.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected 'while' after do.");
|
||||
// TODO 使用更好的错误处理,未来应当采用更好的内存管理器
|
||||
scc_free(statement);
|
||||
return null;
|
||||
@@ -240,7 +251,8 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
*/
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
LOG_ERROR("Expected '(' before like `( expression )` .");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected '(' before like `( expression )` .");
|
||||
}
|
||||
|
||||
scc_ast_type_t *init = null;
|
||||
@@ -253,20 +265,23 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
if (init == null) {
|
||||
init = (scc_ast_type_t *)scc_parse_expression(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon in for statement.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected semicolon in for statement.");
|
||||
}
|
||||
}
|
||||
|
||||
cond = scc_parse_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon in for statement.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected semicolon in for statement.");
|
||||
}
|
||||
|
||||
incr = scc_parse_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("Expected ')' after like `( expression )` .");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ')' after like `( expression )` .");
|
||||
}
|
||||
|
||||
body = scc_parse_statement(parser);
|
||||
@@ -284,7 +299,8 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
if (scc_parser_next_consume(parser, &tok)) {
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme));
|
||||
} else {
|
||||
LOG_ERROR("Expected label after goto.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected label after goto.");
|
||||
}
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) {
|
||||
scc_ast_stmt_continue_init(stmt);
|
||||
@@ -297,7 +313,8 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon after jump statement.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected semicolon after jump statement.");
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
@@ -319,7 +336,8 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_expr_init(stmt, expr);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon after expression.");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected semicolon after expression.");
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -212,15 +212,10 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
// 函数说明符
|
||||
case SCC_TOK_INLINE:
|
||||
return true;
|
||||
|
||||
// typedef 名称(标识符也可能是类型说明符)
|
||||
// typedef 名称(标识符也可能是类型说明符)
|
||||
case SCC_TOK_IDENT:
|
||||
// 需要检查标识符是否在符号表中定义为 typedef
|
||||
// 这里简化处理:假设所有标识符都可能是 typedef
|
||||
// 在实际解析器中,需要查询符号表
|
||||
// TODO
|
||||
return false;
|
||||
|
||||
return scc_parse_got_type(
|
||||
parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -250,7 +245,8 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||
// typedef 名称
|
||||
case SCC_TOK_IDENT:
|
||||
// 需要检查标识符是否在符号表中定义为 typedef
|
||||
return true;
|
||||
return scc_parse_got_type(
|
||||
parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -346,50 +342,59 @@ typedef struct {
|
||||
scc_ast_type_t *user_type; // 如果是用户定义类型,直接存储解析结果
|
||||
} type_spec_info_t;
|
||||
|
||||
static cbool check_type_combinations(type_spec_info_t *info) {
|
||||
static cbool check_type_combinations(scc_parser_t *parser,
|
||||
type_spec_info_t *info) {
|
||||
// 基本类型不能同时出现多个(void, char, int, float, double, bool 互斥)
|
||||
int basic_count = info->is_void + info->is_char + info->is_short +
|
||||
info->is_int + info->is_float + info->is_double +
|
||||
info->is_bool;
|
||||
if (basic_count > 1) {
|
||||
LOG_ERROR("Multiple basic type specifiers");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Multiple basic type specifiers");
|
||||
return false;
|
||||
}
|
||||
|
||||
// long 不能与 void/char/float/bool 组合(但可以和 double 组合为 long
|
||||
// double)
|
||||
if (info->is_long && info->is_float) {
|
||||
LOG_ERROR("'long' and 'float' cannot be combined");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'long' and 'float' cannot be combined");
|
||||
return false;
|
||||
}
|
||||
if (info->is_long && info->is_char) {
|
||||
LOG_ERROR("'long' and 'char' cannot be combined");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'long' and 'char' cannot be combined");
|
||||
return false;
|
||||
}
|
||||
if (info->is_long && info->is_bool) {
|
||||
LOG_ERROR("'long' and 'bool' cannot be combined");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'long' and 'bool' cannot be combined");
|
||||
return false;
|
||||
}
|
||||
// long 与 double 可以组合为 long double
|
||||
if (info->is_long_long && info->is_double) {
|
||||
LOG_ERROR("'long long' and 'double' cannot be combined");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'long long' and 'double' cannot be combined");
|
||||
return false;
|
||||
}
|
||||
// short 只能与 int 组合(默认 int),不能与 double/float 等
|
||||
if (info->is_short &&
|
||||
(info->is_double || info->is_float || info->is_bool || info->is_void)) {
|
||||
LOG_ERROR("'short' cannot be combined with this type");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'short' cannot be combined with this type");
|
||||
return false;
|
||||
}
|
||||
// _Complex 只能与 float/double/long double 组合(或单独出现?C99 中
|
||||
// _Complex 本身不是类型,必须跟浮点类型)
|
||||
if (info->is_complex && !info->is_float && !info->is_double) {
|
||||
LOG_ERROR("'complex' must be combined with a floating type");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"'complex' must be combined with a floating type");
|
||||
return false;
|
||||
}
|
||||
// 如果用户定义了类型(struct/typedef),不能与任何其他类型说明符混合
|
||||
if (info->user_type != null && basic_count > 0) {
|
||||
LOG_ERROR(
|
||||
SCC_ERROR(
|
||||
scc_parser_got_current_pos(parser),
|
||||
"Cannot combine user-defined type with basic type specifiers");
|
||||
return false;
|
||||
}
|
||||
@@ -511,7 +516,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
LOG_ERROR("Unexpected EOF in enum specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected EOF in enum specifier");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -532,7 +538,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
} else {
|
||||
LOG_ERROR("Unexpected token in enum specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected token in enum specifier");
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
}
|
||||
@@ -545,6 +552,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, name, &member);
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
@@ -568,7 +576,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
enumeration-constant = constant-expression
|
||||
*/
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) {
|
||||
LOG_ERROR("Expected 'enum'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'");
|
||||
return null;
|
||||
}
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
@@ -589,11 +597,12 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
LOG_ERROR("Unexpected EOF in enum specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected EOF in enum specifier");
|
||||
break;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_parse_expression(parser);
|
||||
scc_ast_expr_t *expr = scc_parse_assignment_expression(parser);
|
||||
if (expr != null) {
|
||||
scc_vec_push(member, expr);
|
||||
continue;
|
||||
@@ -606,7 +615,8 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
} else {
|
||||
LOG_ERROR("Unexpected token in enum specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected token in enum specifier");
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
}
|
||||
@@ -614,6 +624,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, name, &member);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
@@ -625,8 +636,36 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
type_spec_info_t info = {0};
|
||||
if (!scc_parse_is_type_specifier_start(parser))
|
||||
return null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_STRUCT:
|
||||
case SCC_TOK_UNION:
|
||||
info.user_type = parse_record_type(
|
||||
parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT
|
||||
: SCC_AST_TYPE_UNION);
|
||||
goto done;
|
||||
case SCC_TOK_ENUM:
|
||||
info.user_type = parse_enum_type(parser);
|
||||
goto done;
|
||||
case SCC_TOK_IDENT:
|
||||
info.user_type =
|
||||
scc_parse_got_type(parser, scc_cstring_as_cstr(&tok_ptr->lexeme));
|
||||
if (info.user_type == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected type specifier %s",
|
||||
scc_cstring_as_cstr(&tok_ptr->lexeme));
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
Assert(info.user_type != null);
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
break;
|
||||
}
|
||||
@@ -658,7 +697,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
case SCC_TOK_LONG:
|
||||
// long 可以出现两次
|
||||
if (info.is_long_long) {
|
||||
LOG_ERROR("Three 'long's in type specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Three 'long's in type specifier");
|
||||
return null;
|
||||
}
|
||||
if (info.is_long) {
|
||||
@@ -689,7 +729,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
break;
|
||||
case SCC_TOK_SIGNED:
|
||||
if (info.is_unsigned || info.is_signed) {
|
||||
LOG_ERROR("Both 'signed' and 'unsigned' in type specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Both 'signed' and 'unsigned' in type specifier");
|
||||
return null;
|
||||
}
|
||||
info.is_signed = true;
|
||||
@@ -697,7 +738,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
break;
|
||||
case SCC_TOK_UNSIGNED:
|
||||
if (info.is_unsigned || info.is_signed) {
|
||||
LOG_ERROR("Both 'signed' and 'unsigned' in type specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Both 'signed' and 'unsigned' in type specifier");
|
||||
return null;
|
||||
}
|
||||
info.is_unsigned = true;
|
||||
@@ -709,41 +751,28 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
info.is_complex = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
case SCC_TOK_STRUCT:
|
||||
case SCC_TOK_UNION:
|
||||
info.user_type = parse_record_type(
|
||||
parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT
|
||||
: SCC_AST_TYPE_UNION);
|
||||
goto done;
|
||||
case SCC_TOK_ENUM:
|
||||
info.user_type = parse_enum_type(parser);
|
||||
goto done;
|
||||
case SCC_TOK_IDENT:
|
||||
// // 处理 typedef 名称:查符号表获取类型节点
|
||||
// info.user_type = parse_typedef_name(parser);
|
||||
// if (!info.user_type)
|
||||
// return null;
|
||||
goto done;
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (!check_type_combinations(&info)) {
|
||||
if (!check_type_combinations(parser, &info)) {
|
||||
return null;
|
||||
}
|
||||
return build_type_from_info(&info);
|
||||
duplicate_error:
|
||||
LOG_ERROR("Duplicate type specifier");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
return null;
|
||||
}
|
||||
|
||||
static scc_ast_node_t *parse_declarator(scc_parser_t *parser,
|
||||
static scc_ast_type_t *parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
static scc_ast_node_t *
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
@@ -793,18 +822,15 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
scc_ast_decl_t *param = null;
|
||||
while (1) {
|
||||
// FIXME
|
||||
scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser);
|
||||
scc_ast_type_t *type = parse_type_specifier(parser);
|
||||
if (type == null) {
|
||||
break;
|
||||
scc_ast_node_t *node = _scc_parse_type(parser);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
type->quals = spec;
|
||||
|
||||
scc_ast_node_t *node = parse_declarator(parser, type, null);
|
||||
|
||||
if (SCC_AST_IS_A(scc_ast_decl_t, node)) {
|
||||
param = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
// TODO Check validation
|
||||
Assert(param->base.type = SCC_AST_DECL_VAR);
|
||||
param->base.type = SCC_AST_DECL_PARAM;
|
||||
} else if (SCC_AST_IS_A(scc_ast_type_t, node)) {
|
||||
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
@@ -828,23 +854,37 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
}
|
||||
}
|
||||
|
||||
static inline cbool parse_function_parameters_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return false;
|
||||
}
|
||||
if (scc_parse_is_decl_specifier_start(parser)) {
|
||||
return true;
|
||||
}
|
||||
if (tok_ptr->type == SCC_TOK_R_PAREN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void parse_function_parameters(scc_parser_t *parser,
|
||||
scc_ast_decl_vec_t *params) {
|
||||
// FIXME ?
|
||||
// if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
// LOG_ERROR("Expect '('");
|
||||
// SCC_ERROR(scc_parser_got_current_pos(parser),"Expect '('");
|
||||
// }
|
||||
scc_vec_init(*params);
|
||||
parse_parameter_type_list(parser, params);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("expect ')'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'");
|
||||
}
|
||||
}
|
||||
|
||||
static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) {
|
||||
LOG_ERROR("Expect '['");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expect '['");
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
}
|
||||
@@ -874,16 +914,17 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
||||
}
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||
LOG_ERROR("expect ']'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ']'");
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static scc_ast_node_t *parse_declarator(scc_parser_t *parser,
|
||||
static scc_ast_type_t *parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr) {
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident) {
|
||||
/*
|
||||
(6.7.5) declarator:
|
||||
pointer(opt) direct-declarator
|
||||
@@ -901,72 +942,66 @@ static scc_ast_node_t *parse_declarator(scc_parser_t *parser,
|
||||
direct-declarator ( identifier-list(opt) )
|
||||
*/
|
||||
scc_ast_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr);
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr);
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr, tok_ident);
|
||||
}
|
||||
|
||||
static scc_ast_node_t *
|
||||
static scc_ast_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr) {
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_ast_type_t *ret = null;
|
||||
// direct-abstract-declarator
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return (scc_ast_node_t *)base;
|
||||
return base;
|
||||
}
|
||||
|
||||
if (tok_ptr->type == SCC_TOK_IDENT) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
|
||||
scc_ast_node_t *type =
|
||||
parse_direct_declarator(parser, base, delay_pointee_ptr);
|
||||
Assert(SCC_AST_IS_A(scc_ast_type_t, type));
|
||||
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
|
||||
if (type->type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, SCC_AST_CAST_TO(scc_ast_type_t, type),
|
||||
scc_cstring_as_cstr(&tok.lexeme), null);
|
||||
} else {
|
||||
scc_ast_decl_val_init(decl, SCC_AST_CAST_TO(scc_ast_type_t, type),
|
||||
scc_cstring_as_cstr(&tok.lexeme), null);
|
||||
Assert(tok_ident != null);
|
||||
if (tok_ident->type != SCC_TOK_UNKNOWN) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Got double identifier in declarator");
|
||||
return base;
|
||||
}
|
||||
return (scc_ast_node_t *)decl;
|
||||
scc_parser_next_consume(parser, tok_ident);
|
||||
|
||||
return parse_direct_declarator(parser, base, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
} else if (tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||
// () SCC_TOK_L_PAREN
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_ast_type_t *delay_pointee = null;
|
||||
ret = parse_abstract_declarator(parser, null, &delay_pointee);
|
||||
if (ret == null) {
|
||||
if (parse_function_parameters_start(parser)) {
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
scc_ast_type_function_init(ret, base, ¶ms);
|
||||
return (scc_ast_node_t *)parse_direct_declarator(parser, ret,
|
||||
delay_pointee_ptr);
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
} else {
|
||||
ret = parse_declarator(parser, null, &delay_pointee, tok_ident);
|
||||
Assert(ret != null);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("expect ')'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'");
|
||||
}
|
||||
base = (scc_ast_type_t *)parse_direct_declarator(parser, base,
|
||||
delay_pointee_ptr);
|
||||
base = parse_direct_declarator(parser, base, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
Assert(SCC_AST_IS_A(scc_ast_type_t, base));
|
||||
Assert(delay_pointee != null);
|
||||
delay_pointee->pointer.pointee = base;
|
||||
return ret;
|
||||
}
|
||||
return (scc_ast_node_t *)ret;
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
||||
// [] SCC_TOK_L_BRACKET
|
||||
scc_ast_expr_t *size = parse_array_size_type(parser);
|
||||
scc_ast_type_t *ret = ast_type_alloc();
|
||||
base = (scc_ast_type_t *)parse_direct_declarator(parser, base,
|
||||
delay_pointee_ptr);
|
||||
Assert(SCC_AST_IS_A(scc_ast_type_t, base));
|
||||
base =
|
||||
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
|
||||
scc_ast_type_array_init(ret, base, size);
|
||||
return (scc_ast_node_t *)ret;
|
||||
return ret;
|
||||
} else {
|
||||
return (scc_ast_node_t *)base;
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1008,8 +1043,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
// () SCC_TOK_L_PAREN
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_ast_type_t *delay_pointee = null;
|
||||
ret = parse_abstract_declarator(parser, null, &delay_pointee);
|
||||
if (ret == null) {
|
||||
if (parse_function_parameters_start(parser)) {
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
@@ -1017,8 +1051,10 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
return parse_direct_abstract_declarator(parser, ret,
|
||||
delay_pointee_ptr);
|
||||
} else {
|
||||
ret = parse_abstract_declarator(parser, null, &delay_pointee);
|
||||
Assert(ret != null);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("expect ')'");
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'");
|
||||
}
|
||||
base = parse_direct_abstract_declarator(parser, base,
|
||||
delay_pointee_ptr);
|
||||
@@ -1055,12 +1091,33 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
|
||||
if (ret != null) {
|
||||
ret->quals = spec;
|
||||
}
|
||||
scc_ast_node_t *node = parse_declarator(parser, ret, null);
|
||||
if (is_typedef_decl) {
|
||||
Assert(node->type == SCC_AST_DECL_VAR);
|
||||
node->type = SCC_AST_DECL_TYPEDEF;
|
||||
|
||||
scc_lexer_tok_t tok_ident = {0};
|
||||
scc_ast_type_t *type = parse_declarator(parser, ret, null, &tok_ident);
|
||||
|
||||
scc_ast_decl_t *decl = null;
|
||||
if (tok_ident.type == SCC_TOK_IDENT) {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
}
|
||||
return node;
|
||||
const char *name = decl ? scc_cstring_as_cstr(&tok_ident.lexeme) : null;
|
||||
if (is_typedef_decl) {
|
||||
if (decl == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"typedef don't have a ident");
|
||||
parser->errcode = 1;
|
||||
} else {
|
||||
scc_ast_decl_typedef_init(decl, name, type);
|
||||
}
|
||||
} else if (decl) {
|
||||
if (type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, type, name, null);
|
||||
} else {
|
||||
scc_ast_decl_val_init(decl, type, name, null);
|
||||
}
|
||||
}
|
||||
|
||||
return decl != null ? &decl->base : &type->base;
|
||||
}
|
||||
|
||||
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
(void)context;
|
||||
@@ -70,9 +71,10 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
scc_vec_push(unit->declarations, decl);
|
||||
} else {
|
||||
break;
|
||||
// MAYBE return or next
|
||||
}
|
||||
if (parser->errcode != 0) { // FIXME errcode
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d",
|
||||
parser->errcode);
|
||||
break;
|
||||
}
|
||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
||||
@@ -83,6 +85,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
|
||||
if (parser->errcode) {
|
||||
// TODO: 清理
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d",
|
||||
parser->errcode);
|
||||
scc_free(unit);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,55 @@
|
||||
#include <scc_sema.h>
|
||||
#include <sema_symtab.h>
|
||||
|
||||
static void type_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
(void)context;
|
||||
(void)node_type;
|
||||
(void)node;
|
||||
return;
|
||||
}
|
||||
|
||||
static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
|
||||
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
Assert(type != null);
|
||||
if (decl->name == null) {
|
||||
return;
|
||||
}
|
||||
if (decl->base.type == SCC_AST_DECL_STRUCT) {
|
||||
scc_ast_type_struct_init(type, decl->name, decl);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_UNION) {
|
||||
scc_ast_type_union_init(type, decl->name, decl);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_ENUM) {
|
||||
scc_ast_type_enum_init(type, decl->name, decl);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) {
|
||||
scc_ast_type_typedef_init(type, decl->name, decl);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static scc_ast_type_t *got_type_callback(void *context, const char *name) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
scc_ast_node_t *node = scc_sema_symtab_lookup_symbol(sema_symtab, name);
|
||||
if (SCC_AST_IS_A(scc_ast_type_t, node)) {
|
||||
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
*type = *(scc_ast_type_t *)node;
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
|
||||
if (sema_symtab == null) {
|
||||
@@ -8,11 +57,19 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
return;
|
||||
}
|
||||
callbacks->context = sema_symtab;
|
||||
callbacks->on_decl = null;
|
||||
callbacks->on_decl = decl_callback;
|
||||
callbacks->on_expr = null;
|
||||
callbacks->on_stmt = null;
|
||||
callbacks->on_type = null;
|
||||
callbacks->got_type = null;
|
||||
callbacks->on_type = type_callback;
|
||||
callbacks->got_type = got_type_callback;
|
||||
|
||||
scc_sema_symtab_init(sema_symtab);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list",
|
||||
&scc_ast_builtin_type_va_list.base);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_size_t",
|
||||
&scc_ast_builtin_type_long_long.base);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_ptrdiff_t",
|
||||
&scc_ast_builtin_type_long_long.base);
|
||||
}
|
||||
|
||||
void scc_sema_drop(scc_sema_callbacks_t *callbacks) {}
|
||||
|
||||
@@ -4,8 +4,8 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||
symtab->root_scope.parent = null;
|
||||
|
||||
scc_hashtable_init(&symtab->root_scope.symbols,
|
||||
(scc_hashtable_hash_func_t)scc_strcmp,
|
||||
(scc_hashtable_equal_func_t)scc_strhash32);
|
||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
||||
symtab->current_scope = &symtab->root_scope;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user