- 在scc_abi_base_type_kind枚举中添加SCC_ABI_TYPE_VA_LIST类型 - 为Windows x64平台实现VA_LIST类型的ABI规则,遵循MSVC调用约定 - 在AST到ABI类型转换中处理SCC_AST_BUILTIN_TYPE_VA_LIST和BOOL类型 refactor(ast2ir): 实现循环控制流和跳转语句转换 - 添加break和continue缓存表用于语句跳转目标管理 - 实现while、do-while和for循环的正确控制流结构 - 添加对break、continue、goto和label语句的IR转换支持 - 修复复合表达式和声明类型的处理逻辑 refactor(parser): 重构语义分析接口和循环语句解析 - 将语义分析上下文从回调结构改为指针传递 - 为switch、while、do-while和for语句添加BEGIN/END语义标记 - 实现匿名结构体/联合体/枚举的符号命名处理 - 优化结构体/联合体/枚举声明的类型解析逻辑 feat(parser): 实现跳转语句语义分析和符号绑定 - 添加break_stack和continue_stack用于跟踪循环层级 - 实现break和continue语句的目标语句绑定检查 - 支持goto和label语句的标签符号查找和绑定 - 添加对跳转语句位置的有效性验证 Co-authored-by: Copilot <copilot@github.com>
366 lines
12 KiB
C
366 lines
12 KiB
C
/*
|
|
A.2.2 Declarations
|
|
|
|
(6.7) declaration:
|
|
declaration-specifiers init-declarator-list(opt) ;
|
|
(6.7) declaration-specifiers:
|
|
storage-class-specifier declaration-specifiers(opt)
|
|
type-specifier declaration-specifiers(opt)
|
|
type-qualifier declaration-specifiers(opt)
|
|
function-specifier declaration-specifiers(opt)
|
|
(6.7) init-declarator-list:
|
|
init-declarator
|
|
init-declarator-list , init-declarator
|
|
(6.7) init-declarator:
|
|
declarator
|
|
declarator = initializer
|
|
(6.7.1) storage-class-specifier:
|
|
typedef
|
|
extern
|
|
static
|
|
auto
|
|
register
|
|
(6.7.2) type-specifier:
|
|
void
|
|
char
|
|
short
|
|
int
|
|
long
|
|
float
|
|
double
|
|
signed
|
|
unsigned
|
|
_Bool
|
|
_Complex
|
|
struct-or-union-specifier
|
|
enum-specifier
|
|
typedef-name
|
|
(6.7.2.1) struct-or-union-specifier:
|
|
struct-or-union identifier(opt) { struct-declaration-list }
|
|
struct-or-union identifier
|
|
(6.7.2.1) struct-or-union:
|
|
struct
|
|
union
|
|
(6.7.2.1) struct-declaration-list:
|
|
struct-declaration
|
|
struct-declaration-list struct-declaration
|
|
(6.7.2.1) struct-declaration:
|
|
specifier-qualifier-list struct-declarator-list ;
|
|
(6.7.2.1) specifier-qualifier-list:
|
|
type-specifier specifier-qualifier-list(opt)
|
|
type-qualifier specifier-qualifier-list(opt)
|
|
(6.7.2.1) struct-declarator-list:
|
|
struct-declarator
|
|
struct-declarator-list , struct-declarator
|
|
(6.7.2.1) struct-declarator:
|
|
declarator
|
|
declarator(opt) : constant-expression
|
|
(6.7.2.2) enum-specifier:
|
|
enum identifier(opt) { enumerator-list }
|
|
enum identifier(opt) { enumerator-list , }
|
|
enum identifier
|
|
(6.7.2.2) enumerator-list:
|
|
enumerator
|
|
enumerator-list , enumerator
|
|
(6.7.2.2) enumerator:
|
|
enumeration-constant
|
|
enumeration-constant = constant-expression
|
|
(6.7.3) type-qualifier:
|
|
const
|
|
restrict
|
|
volatile
|
|
(6.7.4) function-specifier:
|
|
inline
|
|
(6.7.5) declarator:
|
|
pointer(opt) direct-declarator
|
|
(6.7.5) direct-declarator:
|
|
identifier
|
|
( declarator )
|
|
direct-declarator [ type-qualifier-list(opt)
|
|
assignment-expression(opt) ]
|
|
direct-declarator [ static type-qualifier-list(opt)
|
|
assignment-expression ]
|
|
direct-declarator [ type-qualifier-list static
|
|
assignment-expression ]
|
|
direct-declarator [ type-qualifier-list(opt) * ]
|
|
direct-declarator ( parameter-type-list )
|
|
direct-declarator ( identifier-list(opt) )
|
|
(6.7.5) pointer:
|
|
* type-qualifier-list(opt)
|
|
* type-qualifier-list(opt) pointer
|
|
(6.7.5) type-qualifier-list:
|
|
type-qualifier
|
|
type-qualifier-list type-qualifier
|
|
(6.7.5) parameter-type-list:
|
|
parameter-list
|
|
parameter-list , ...
|
|
(6.7.5) parameter-list:
|
|
parameter-declaration
|
|
parameter-list , parameter-declaration
|
|
(6.7.5) parameter-declaration:
|
|
declaration-specifiers declarator
|
|
declaration-specifiers abstract-declarator(opt)
|
|
(6.7.5) identifier-list:
|
|
identifier
|
|
identifier-list , identifier
|
|
(6.7.6) type-name:
|
|
specifier-qualifier-list abstract-declarator(opt)
|
|
(6.7.6) abstract-declarator:
|
|
pointer
|
|
pointer(opt) direct-abstract-declarator
|
|
(6.7.6) direct-abstract-declarator:
|
|
( abstract-declarator )
|
|
direct-abstract-declarator(opt) [ type-qualifier-list (opt)
|
|
assignment-expression(opt) ]
|
|
direct-abstract-declarator(opt) [ static type-qualifier-list(opt)
|
|
assignment-expression ]
|
|
direct-abstract-declarator(opt) [ type-qualifier-list static
|
|
assignment-expression ]
|
|
direct-abstract-declarator(opt) [ * ]
|
|
direct-abstract-declarator(opt) ( parameter-type-list(opt) )
|
|
(6.7.7) typedef-name:
|
|
identifier
|
|
(6.7.8) initializer:
|
|
assignment-expression
|
|
{ initializer-list }
|
|
{ initializer-list , }
|
|
(6.7.8) initializer-list:
|
|
designation(opt) initializer
|
|
initializer-list , designation(opt) initializer
|
|
(6.7.8) designation:
|
|
designator-list =
|
|
(6.7.8) designator-list:
|
|
designator
|
|
designator-list designator
|
|
(6.7.8) designator:
|
|
[ constant-expression ]
|
|
. identifier
|
|
|
|
A.2.4 External definitions
|
|
|
|
(6.9) translation-unit:
|
|
external-declaration
|
|
translation-unit external-declaration
|
|
(6.9) external-declaration:
|
|
function-definition
|
|
declaration
|
|
(6.9.1) function-definition:
|
|
declaration-specifiers declarator declaration-list(opt) compound-statement
|
|
(6.9.1) declaration-list:
|
|
declaration
|
|
declaration-list declaration
|
|
*/
|
|
|
|
#include <parser_utils.h>
|
|
#include <scc_ast_utils.h>
|
|
#include <scc_parser.h>
|
|
|
|
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|
scc_ast_expr_t *base) {
|
|
/*
|
|
initializer:
|
|
assignment-expression
|
|
{ initializer-list }
|
|
{ initializer-list , }
|
|
initializer-list:
|
|
designation(opt) initializer
|
|
initializer-list , designation(opt) initializer
|
|
designation:
|
|
designator-list =
|
|
designator-list:
|
|
designator
|
|
designator-list designator
|
|
designator:
|
|
[ constant-expression ]
|
|
. identifier
|
|
*/
|
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
|
scc_lexer_tok_t tok = {0};
|
|
tok_ptr = scc_parser_peek(parser);
|
|
scc_ast_expr_t *init = nullptr;
|
|
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
|
// TODO int a = 1, b = 1;
|
|
init = scc_parse_assignment_expression(parser);
|
|
return init;
|
|
}
|
|
scc_parser_next_consume(parser, &tok);
|
|
scc_pos_t pos = tok.loc;
|
|
scc_lexer_tok_drop(&tok);
|
|
|
|
init = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
|
Assert(init != nullptr);
|
|
scc_ast_expr_vec_t lhs_exprs;
|
|
scc_vec_init(lhs_exprs);
|
|
scc_ast_expr_vec_t rhs_exprs;
|
|
scc_vec_init(rhs_exprs);
|
|
scc_ast_expr_t *lhs = nullptr;
|
|
scc_ast_expr_t *rhs = nullptr;
|
|
scc_ast_expr_t *ptr = base;
|
|
while (1) {
|
|
tok_ptr = scc_parser_peek(parser);
|
|
if (tok_ptr->type == SCC_TOK_DOT) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
tok_ptr = scc_parser_peek(parser);
|
|
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
|
scc_parser_next_consume(parser, &tok);
|
|
lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
|
Assert(lhs != nullptr);
|
|
scc_ast_expr_member_init(lhs, ptr, scc_str_as_cstr(&tok.lexeme),
|
|
tok.loc);
|
|
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
|
ptr = lhs;
|
|
continue;
|
|
}
|
|
rhs = scc_parse_initializer(parser, lhs);
|
|
if (rhs == nullptr) {
|
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
|
"Expected initializer");
|
|
Panic();
|
|
}
|
|
scc_vec_push(lhs_exprs, lhs);
|
|
scc_vec_push(rhs_exprs, rhs);
|
|
ptr = base;
|
|
} else {
|
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
|
"Expected 'identifier' after '.'");
|
|
}
|
|
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
scc_ast_expr_t *idx = scc_parser_constant_expression(parser);
|
|
Assert(idx != nullptr);
|
|
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'");
|
|
}
|
|
lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
|
Assert(lhs != nullptr);
|
|
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
|
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
|
ptr = lhs;
|
|
continue;
|
|
}
|
|
rhs = scc_parse_initializer(parser, lhs);
|
|
Assert(rhs != nullptr);
|
|
scc_vec_push(lhs_exprs, lhs);
|
|
scc_vec_push(rhs_exprs, rhs);
|
|
ptr = base;
|
|
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
break;
|
|
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
continue;
|
|
} else {
|
|
// FIXME
|
|
scc_ast_expr_t *expr = scc_parse_initializer(parser, base);
|
|
scc_vec_push(lhs_exprs, nullptr);
|
|
scc_vec_push(rhs_exprs, expr);
|
|
}
|
|
}
|
|
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs, pos);
|
|
return init;
|
|
}
|
|
|
|
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
|
|
|
scc_ast_decl_t *decl_list = nullptr;
|
|
scc_ast_decl_vec_t decl_list_vec;
|
|
scc_vec_init(decl_list_vec);
|
|
|
|
scc_ast_qual_type_t *type = scc_parse_declaration_specifiers(parser);
|
|
if (type == nullptr) {
|
|
return nullptr;
|
|
}
|
|
scc_ast_decl_specifier_t spec = type->quals;
|
|
// FIXME drop typedef inline and ...
|
|
type->quals.is_typedef = false;
|
|
|
|
scc_ast_decl_t *decl = nullptr;
|
|
CONTINUE:
|
|
decl = scc_parse_declarator(parser, type);
|
|
if (decl == nullptr) {
|
|
return nullptr;
|
|
}
|
|
tok_ptr = scc_parser_peek(parser);
|
|
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
// TODO maybe memory leak
|
|
scc_ast_expr_t *lvalue = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
|
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) {
|
|
scc_parse_decl_sema(parser, decl);
|
|
scc_sema_decl(parser, scc_ast_decl_t_BEGIN, nullptr);
|
|
// FIXME hack struct
|
|
scc_vec_foreach(decl->func.type->type->function.params, i) {
|
|
scc_ast_decl_t *param =
|
|
scc_vec_at(decl->func.type->type->function.params, i);
|
|
// Add params to decl
|
|
scc_parse_decl_sema(parser, param);
|
|
}
|
|
scc_ast_stmt_t *body = scc_parse_statement(parser);
|
|
scc_sema_decl(parser, scc_ast_decl_t_END, nullptr);
|
|
Assert(decl->base.type == SCC_AST_DECL_FUNC);
|
|
decl->func.body = body;
|
|
Assert(decl->func.type != nullptr);
|
|
Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION);
|
|
Assert(decl->func.body != nullptr);
|
|
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
|
|
goto RETURN;
|
|
}
|
|
|
|
tok_ptr = scc_parser_peek(parser);
|
|
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
if (decl_list)
|
|
scc_vec_push(decl_list_vec, decl);
|
|
if (spec.is_typedef) {
|
|
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,
|
|
decl->base.loc);
|
|
}
|
|
} else {
|
|
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type,
|
|
decl->base.loc);
|
|
}
|
|
}
|
|
if (decl_list != nullptr) {
|
|
scc_vec_foreach(decl_list_vec, i) {
|
|
decl = scc_vec_at(decl_list_vec, i);
|
|
scc_parse_decl_sema(parser, decl);
|
|
}
|
|
// 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);
|
|
}
|
|
goto RETURN;
|
|
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
|
scc_parser_next_consume(parser, nullptr);
|
|
if (decl_list == nullptr) {
|
|
decl_list = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
|
Assert(decl_list != nullptr);
|
|
scc_vec_push(decl_list_vec, decl);
|
|
} else {
|
|
Assert(scc_vec_size(decl_list_vec) != 0);
|
|
decl->var.type = scc_vec_at(decl_list_vec, 0)->var.type;
|
|
scc_vec_push(decl_list_vec, decl);
|
|
}
|
|
goto CONTINUE;
|
|
} else {
|
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
|
"Expected ';' or '=' or '{'");
|
|
// FIXME memory leak
|
|
goto ERROR;
|
|
}
|
|
|
|
RETURN:
|
|
return decl;
|
|
ERROR:
|
|
return nullptr;
|
|
}
|