feat(ast): 添加汇编器模块并改进AST定义和IR转换
- 在README.md中添加asm汇编器模块说明 - 更新ast_def.h中的枚举注释,添加sema相关信息以明确语义分析作用域 - 重命名函数参数param_types为params,使命名更清晰 - 移除call表达式中的_target字段,简化结构 - 为member、identifier等字段添加///< fill by sema注释说明填充时机 - 为jump语句添加_target字段用于语义分析 - 更新所有AST初始化函数,接受位置信息参数以改进错误定位 - 修复alignof表达式的类型应为ALIGN_OF而非SIZE_OF的问题 - 重构ast2ir.h,引入scc_ast2ir_ctx_t上下文结构体统一管理转换状态 - 添加符号表、节点到IR映射等必要的转换上下文信息
This commit is contained in:
@@ -87,6 +87,20 @@ static inline void scc_parse_decl_sema(scc_parser_t *parser,
|
||||
decl);
|
||||
}
|
||||
|
||||
static inline void scc_parse_expr_sema(scc_parser_t *parser,
|
||||
scc_ast_expr_t *expr) {
|
||||
parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
|
||||
expr ? expr->base.type : SCC_AST_UNKNOWN,
|
||||
expr);
|
||||
}
|
||||
|
||||
static inline void scc_parse_stmt_sema(scc_parser_t *parser,
|
||||
scc_ast_stmt_t *stmt) {
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
stmt ? stmt->base.type : SCC_AST_UNKNOWN,
|
||||
stmt);
|
||||
}
|
||||
|
||||
static inline void scc_parse_type_sema(scc_parser_t *parser,
|
||||
scc_ast_type_t *type) {
|
||||
parser->sema_callbacks.on_type(parser->sema_callbacks.context,
|
||||
|
||||
@@ -182,7 +182,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
init = scc_parse_assignment_expression(parser);
|
||||
return init;
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
init = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(init != null);
|
||||
@@ -202,8 +204,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_member_init(lhs, ptr,
|
||||
scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_expr_member_init(
|
||||
lhs, ptr, scc_cstring_as_cstr(&tok.lexeme), tok.loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
@@ -230,7 +232,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx);
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
@@ -253,7 +255,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_vec_push(rhs_exprs, expr);
|
||||
}
|
||||
}
|
||||
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs);
|
||||
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs, pos);
|
||||
return init;
|
||||
}
|
||||
|
||||
@@ -283,10 +285,14 @@ CONTINUE:
|
||||
scc_parser_next_consume(parser, null);
|
||||
// TODO maybe memory leak
|
||||
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type);
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
||||
decl->var.init = scc_parse_initializer(parser, lvalue);
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_BEGIN, null);
|
||||
scc_ast_stmt_t *body = scc_parse_statement(parser);
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_END, null);
|
||||
Assert(decl->base.type == SCC_AST_DECL_FUNC);
|
||||
decl->func.body = body;
|
||||
Assert(decl->func.type != null);
|
||||
@@ -305,10 +311,12 @@ CONTINUE:
|
||||
if (decl_list) {
|
||||
scc_vec_foreach(decl_list_vec, i) {
|
||||
decl = scc_vec_at(decl_list_vec, i);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type,
|
||||
decl->base.loc);
|
||||
}
|
||||
} else {
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type,
|
||||
decl->base.loc);
|
||||
}
|
||||
}
|
||||
if (decl_list != null) {
|
||||
@@ -316,7 +324,9 @@ CONTINUE:
|
||||
decl = scc_vec_at(decl_list_vec, i);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
}
|
||||
scc_ast_decl_list_init(decl_list, &decl_list_vec);
|
||||
// FIXME
|
||||
scc_ast_decl_list_init(decl_list, &decl_list_vec,
|
||||
scc_vec_at(decl_list_vec, 0)->base.loc);
|
||||
decl = decl_list;
|
||||
} else {
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
|
||||
@@ -374,7 +374,8 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, op, left, right);
|
||||
// FIXME pos
|
||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
@@ -391,6 +392,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return left;
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
|
||||
int prec = get_token_precedence(tok_ptr->type);
|
||||
if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) {
|
||||
@@ -411,7 +413,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, op, left, right);
|
||||
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
@@ -425,6 +427,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
|
||||
// 消耗 '?'
|
||||
scc_lexer_tok_t q_tok;
|
||||
@@ -456,7 +459,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(cond != null);
|
||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr);
|
||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
||||
cond_expr = cond;
|
||||
}
|
||||
return cond_expr;
|
||||
@@ -480,13 +483,15 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
if (!operand) {
|
||||
// FIXME postfix-expression
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
// FIXME pos
|
||||
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
||||
operand = scc_parse_initializer(parser, expr);
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_cast_init(expr, type, operand);
|
||||
// FIXME pos
|
||||
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
||||
return expr;
|
||||
} else {
|
||||
// 不是类型转换,回退
|
||||
@@ -538,6 +543,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
// 一元运算符右结合,递归调用 parse_unary_expression
|
||||
@@ -556,7 +562,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_unary_init(expr, op, operand);
|
||||
scc_ast_expr_unary_init(expr, op, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_SIZEOF:
|
||||
@@ -573,6 +579,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr.loc;
|
||||
scc_lexer_tok_drop(&tok_ptr);
|
||||
|
||||
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
||||
@@ -599,14 +606,14 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
Assert(type_name != null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null, pos);
|
||||
return expr;
|
||||
}
|
||||
next:
|
||||
// 尝试解析 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (operand != null) {
|
||||
scc_ast_expr_sizeof_init(expr, null, operand);
|
||||
scc_ast_expr_sizeof_init(expr, null, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -618,11 +625,14 @@ next:
|
||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
if (!left) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
|
||||
return null;
|
||||
}
|
||||
pos = tok_ptr->loc;
|
||||
|
||||
scc_parser_store(parser);
|
||||
scc_parser_next(parser);
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||
@@ -635,7 +645,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
scc_ast_expr_lvalue_init(expr, type, pos);
|
||||
left = scc_parse_initializer(parser, expr);
|
||||
return left;
|
||||
}
|
||||
@@ -650,6 +660,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
|
||||
scc_ast_expr_t *index = scc_parse_expression(parser);
|
||||
if (!index) {
|
||||
@@ -664,7 +675,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(subscript != null);
|
||||
scc_ast_expr_array_subscript_init(subscript, left, index);
|
||||
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
||||
left = subscript;
|
||||
break;
|
||||
}
|
||||
@@ -672,6 +683,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
scc_ast_expr_vec_t args;
|
||||
scc_vec_init(args);
|
||||
|
||||
@@ -700,7 +712,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(call != null);
|
||||
scc_ast_expr_call_init(call, left, &args);
|
||||
scc_ast_expr_call_init(call, left, &args, pos);
|
||||
left = call;
|
||||
break;
|
||||
}
|
||||
@@ -723,9 +735,9 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(member != null);
|
||||
if (op_tok.type == SCC_TOK_DOT) {
|
||||
scc_ast_expr_member_init(member, left, name);
|
||||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
||||
} else {
|
||||
scc_ast_expr_ptr_member_init(member, left, name);
|
||||
scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc);
|
||||
}
|
||||
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
@@ -739,10 +751,10 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
return left;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_unary_init(expr, op, left);
|
||||
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
left = expr;
|
||||
break;
|
||||
}
|
||||
@@ -776,7 +788,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_INT_LITERAL: {
|
||||
@@ -785,7 +798,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_FLOAT_LITERAL: {
|
||||
@@ -794,7 +807,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_CHAR_LITERAL: {
|
||||
@@ -803,7 +816,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_STRING_LITERAL: {
|
||||
@@ -825,8 +838,9 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
// FIXME loc
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
|
||||
true);
|
||||
true, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
@@ -847,7 +861,12 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
if (!left)
|
||||
return null;
|
||||
|
||||
while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||||
if (!right) {
|
||||
parser_sync(parser);
|
||||
@@ -855,7 +874,8 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right);
|
||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right,
|
||||
tok_ptr->loc);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
|
||||
@@ -73,7 +73,8 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (!scc_parser_next_consume(parser, &tok)) {
|
||||
return null;
|
||||
@@ -91,11 +92,13 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement);
|
||||
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement,
|
||||
pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
||||
return null;
|
||||
}
|
||||
@@ -120,11 +123,12 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_case_init(stmt, expr, statement);
|
||||
scc_ast_stmt_case_init(stmt, expr, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
||||
return null;
|
||||
}
|
||||
@@ -141,17 +145,20 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_default_init(stmt, statement);
|
||||
scc_ast_stmt_default_init(stmt, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||
return null;
|
||||
}
|
||||
scc_ast_block_item_vec_t block_items;
|
||||
scc_vec_init(block_items);
|
||||
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_BEGIN, null);
|
||||
while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
|
||||
/// TODO
|
||||
// scc_parse_is_decl();
|
||||
@@ -168,13 +175,15 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
}
|
||||
scc_vec_push(block_items, ret);
|
||||
}
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_END, null);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_compound_init(stmt, &block_items);
|
||||
scc_ast_stmt_compound_init(stmt, &block_items, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
||||
return null;
|
||||
}
|
||||
@@ -190,11 +199,12 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else);
|
||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||
return null;
|
||||
}
|
||||
@@ -203,11 +213,12 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_switch_init(stmt, expression, statement);
|
||||
scc_ast_stmt_switch_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||
return null;
|
||||
}
|
||||
@@ -216,11 +227,12 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_while_init(stmt, expression, statement);
|
||||
scc_ast_stmt_while_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||
return null;
|
||||
}
|
||||
@@ -237,11 +249,12 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement);
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
||||
return null;
|
||||
}
|
||||
@@ -288,27 +301,28 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
body = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_for_init(stmt, init, cond, incr, body);
|
||||
scc_ast_stmt_for_init(stmt, init, cond, incr, body, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (scc_parser_next_consume(parser, &tok)) {
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme), pos);
|
||||
} else {
|
||||
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);
|
||||
scc_ast_stmt_continue_init(stmt, pos);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_BREAK)) {
|
||||
scc_ast_stmt_break_init(stmt);
|
||||
scc_ast_stmt_break_init(stmt, pos);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_RETURN)) {
|
||||
scc_ast_stmt_return_init(stmt, scc_parse_expression(parser));
|
||||
scc_ast_stmt_return_init(stmt, scc_parse_expression(parser), pos);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -320,11 +334,12 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, null);
|
||||
scc_ast_stmt_expr_init(stmt, null, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -334,7 +349,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, expr);
|
||||
scc_ast_stmt_expr_init(stmt, expr, pos);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
@@ -350,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
if (!tok_ref) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ref->loc;
|
||||
switch (tok_ref->type) {
|
||||
/*
|
||||
(6.8.1)
|
||||
@@ -366,14 +382,14 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
scc_parser_reset(parser);
|
||||
stmt = parse_label_statement(parser);
|
||||
stmt = parse_label_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_CASE: {
|
||||
stmt = parse_case_statement(parser);
|
||||
stmt = parse_case_statement(parser, pos);
|
||||
goto RETURN;
|
||||
}
|
||||
case SCC_TOK_DEFAULT:
|
||||
stmt = parse_default_statement(parser);
|
||||
stmt = parse_default_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.2)
|
||||
@@ -389,7 +405,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_L_BRACE:
|
||||
stmt = parse_compound_statement(parser);
|
||||
stmt = parse_compound_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.4)
|
||||
@@ -399,10 +415,10 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
switch ( expression ) statement
|
||||
*/
|
||||
case SCC_TOK_IF:
|
||||
stmt = parse_if_statement(parser);
|
||||
stmt = parse_if_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_SWITCH:
|
||||
stmt = parse_switch_statement(parser);
|
||||
stmt = parse_switch_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.5)
|
||||
@@ -415,13 +431,13 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_WHILE:
|
||||
stmt = parse_while_statement(parser);
|
||||
stmt = parse_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_DO:
|
||||
stmt = parse_do_while_statement(parser);
|
||||
stmt = parse_do_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_FOR:
|
||||
stmt = parse_for_statement(parser);
|
||||
stmt = parse_for_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.6)
|
||||
@@ -435,7 +451,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
case SCC_TOK_CONTINUE:
|
||||
case SCC_TOK_BREAK:
|
||||
case SCC_TOK_RETURN:
|
||||
stmt = parse_jump_statement(parser);
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
default:
|
||||
break;
|
||||
@@ -445,12 +461,9 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
expression-statement:
|
||||
expression(opt) ;
|
||||
*/
|
||||
stmt = parse_expression_statement(parser);
|
||||
stmt = parse_expression_statement(parser, pos);
|
||||
RETURN:
|
||||
scc_parser_reset(parser);
|
||||
if (stmt) {
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
stmt->base.type, stmt);
|
||||
}
|
||||
scc_parse_stmt_sema(parser, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -467,7 +467,8 @@ static cbool check_type_combinations(scc_parser_t *parser,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static scc_ast_type_t *build_type_from_info(type_spec_info_t *info) {
|
||||
static scc_ast_type_t *build_type_from_info(type_spec_info_t *info,
|
||||
scc_pos_t pos) {
|
||||
// 如果有用户定义类型,直接返回(注意可能需要复制或共享)
|
||||
if (info->user_type) {
|
||||
return info->user_type; // 假设 parse_struct_union_enum 已分配好节点
|
||||
@@ -528,7 +529,7 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info) {
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
_scc_ast_type_builtin_init(type, builtin);
|
||||
_scc_ast_type_builtin_init(type, builtin, pos);
|
||||
// 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责
|
||||
return type;
|
||||
}
|
||||
@@ -564,9 +565,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
declarator(opt) : constant-expression
|
||||
*/
|
||||
// FIXME check struct/union
|
||||
scc_parser_next_consume(parser, null);
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_lexer_tok_t tok;
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
scc_ast_decl_vec_t member;
|
||||
@@ -614,9 +618,9 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
if (type_kind == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, name, &member);
|
||||
scc_ast_decl_struct_init(decl, name, &member, pos);
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, name, &member);
|
||||
scc_ast_decl_union_init(decl, name, &member, pos);
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
@@ -629,7 +633,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
_scc_ast_type_record_init(type, type_kind, name, decl);
|
||||
_scc_ast_type_record_init(type, type_kind, name, decl, pos);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -649,12 +653,16 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
enumeration-constant
|
||||
enumeration-constant = constant-expression
|
||||
*/
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) {
|
||||
scc_lexer_tok_t tok;
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
if (tok.type != SCC_TOK_ENUM) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'");
|
||||
return null;
|
||||
}
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_lexer_tok_t tok;
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
scc_ast_expr_vec_t member;
|
||||
@@ -697,7 +705,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_ast_decl_enum_init(decl, name, &member, pos);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
@@ -709,7 +717,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
scc_ast_type_enum_init(type, name, decl);
|
||||
scc_ast_type_enum_init(type, name, decl, pos);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -719,6 +727,10 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
return null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_STRUCT:
|
||||
@@ -840,7 +852,7 @@ done:
|
||||
if (!check_type_combinations(parser, &info)) {
|
||||
return null;
|
||||
}
|
||||
return build_type_from_info(&info);
|
||||
return build_type_from_info(&info, pos);
|
||||
duplicate_error:
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
return null;
|
||||
@@ -858,6 +870,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_MUL) {
|
||||
return pointee;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
scc_parser_next_consume(parser, null);
|
||||
|
||||
scc_ast_type_t *pointer = ast_type_alloc();
|
||||
@@ -866,7 +879,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
*delay_pointee_ptr = pointer;
|
||||
pointee = pointer;
|
||||
}
|
||||
scc_ast_type_pointer_init(pointer, pointee);
|
||||
scc_ast_type_pointer_init(pointer, pointee, pos);
|
||||
pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
|
||||
|
||||
return parse_pointer(parser, pointer, delay_pointee_ptr);
|
||||
@@ -887,6 +900,7 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
*/
|
||||
scc_ast_decl_t *param = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
while (1) {
|
||||
// FIXME
|
||||
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
|
||||
@@ -904,14 +918,20 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
param->base.type = SCC_AST_DECL_PARAM;
|
||||
|
||||
scc_vec_push(*params, param);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ELLIPSIS)) {
|
||||
|
||||
scc_parser_next_consume(parser, null);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_ELLIPSIS) {
|
||||
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(param != null);
|
||||
// FIXME
|
||||
scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null);
|
||||
scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null,
|
||||
tok_ptr->loc);
|
||||
scc_vec_push(*params, param);
|
||||
break;
|
||||
}
|
||||
@@ -1041,7 +1061,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
scc_ast_type_function_init(ret, base, ¶ms);
|
||||
// FIXME
|
||||
scc_ast_type_function_init(ret, base, ¶ms, base->base.loc);
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
} else {
|
||||
@@ -1063,7 +1084,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t *ret = ast_type_alloc();
|
||||
base =
|
||||
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
|
||||
scc_ast_type_array_init(ret, base, size);
|
||||
// FIXME
|
||||
scc_ast_type_array_init(ret, base, size, base->base.loc);
|
||||
return ret;
|
||||
} else {
|
||||
return base;
|
||||
@@ -1112,7 +1134,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
scc_ast_type_function_init(ret, base, ¶ms);
|
||||
// FIXME
|
||||
scc_ast_type_function_init(ret, base, ¶ms, base->base.loc);
|
||||
return parse_direct_abstract_declarator(parser, ret,
|
||||
delay_pointee_ptr);
|
||||
} else {
|
||||
@@ -1133,7 +1156,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t *ret = ast_type_alloc();
|
||||
base =
|
||||
parse_direct_abstract_declarator(parser, base, delay_pointee_ptr);
|
||||
scc_ast_type_array_init(ret, base, size);
|
||||
// FIXME
|
||||
scc_ast_type_array_init(ret, base, size, base->base.loc);
|
||||
return ret;
|
||||
} else {
|
||||
return base;
|
||||
@@ -1157,7 +1181,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
: null;
|
||||
|
||||
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, decl_type, name, null);
|
||||
scc_ast_decl_func_init(decl, decl_type, name, null, decl_name_tok.loc);
|
||||
// TODO using sema to change it
|
||||
if (type->quals.is_inline) {
|
||||
decl_type->quals.is_inline = true;
|
||||
@@ -1165,7 +1189,8 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
type->quals.is_inline = false;
|
||||
}
|
||||
} else {
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null);
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null,
|
||||
decl_name_tok.loc);
|
||||
}
|
||||
|
||||
if (decl_name_tok.type != SCC_TOK_IDENT) {
|
||||
@@ -1175,10 +1200,11 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
if (decl_type->base.type == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name,
|
||||
null);
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name, null);
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
} else {
|
||||
decl = decl_type->record.decl;
|
||||
@@ -1188,14 +1214,16 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
if (decl_type->enumeration.decl == null) {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, type->enumeration.name, null);
|
||||
scc_ast_decl_enum_init(decl, type->enumeration.name, null,
|
||||
decl_type->base.loc);
|
||||
} else {
|
||||
decl = type->enumeration.decl;
|
||||
scc_free(decl_type); // FIXME
|
||||
}
|
||||
} else {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null);
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
}
|
||||
return decl;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <scc_pos_log.h>
|
||||
#include <scc_sema.h>
|
||||
#include <sema_symtab.h>
|
||||
|
||||
@@ -10,12 +11,55 @@ static void type_callback(void *context, scc_ast_node_type_t node_type,
|
||||
return;
|
||||
}
|
||||
|
||||
static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
static void expr_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
scc_ast_expr_t *decl = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
||||
scc_ast_node_t *node =
|
||||
scc_sema_symtab_lookup_symbol(sema_symtab, decl->identifier.name);
|
||||
if (node == null) {
|
||||
SCC_ERROR(decl->base.loc, "Identifier '%s' not found",
|
||||
decl->identifier.name);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stmt_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
|
||||
if (node_type == scc_ast_stmt_t_BEGIN) {
|
||||
scc_sema_symtab_enter_scope(sema_symtab);
|
||||
return;
|
||||
} else if (node_type == scc_ast_stmt_t_END) {
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
if (node_type == scc_ast_decl_t_BEGIN) {
|
||||
scc_sema_symtab_enter_scope(sema_symtab);
|
||||
return;
|
||||
} else if (node_type == scc_ast_decl_t_END) {
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
@@ -24,25 +68,25 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
return;
|
||||
}
|
||||
if (decl->base.type == SCC_AST_DECL_STRUCT) {
|
||||
scc_ast_type_struct_init(type, decl->name, decl);
|
||||
scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$S_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_UNION) {
|
||||
scc_ast_type_union_init(type, decl->name, decl);
|
||||
scc_ast_type_union_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$U_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_ENUM) {
|
||||
scc_ast_type_enum_init(type, decl->name, decl);
|
||||
scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$E_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) {
|
||||
scc_ast_type_typedef_init(type, decl->name, decl);
|
||||
scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
}
|
||||
return;
|
||||
@@ -67,8 +111,8 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
}
|
||||
callbacks->context = sema_symtab;
|
||||
callbacks->on_decl = decl_callback;
|
||||
callbacks->on_expr = null;
|
||||
callbacks->on_stmt = null;
|
||||
callbacks->on_expr = expr_callback;
|
||||
callbacks->on_stmt = stmt_callback;
|
||||
callbacks->on_type = type_callback;
|
||||
callbacks->got_type = got_type_callback;
|
||||
|
||||
|
||||
5
libs/parser/tests/test_sema_unit.c
Normal file
5
libs/parser/tests/test_sema_unit.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <utest/acutest.h>
|
||||
|
||||
TEST_LIST = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
Reference in New Issue
Block a user