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:
zzy
2026-03-12 14:57:35 +08:00
parent 30ac2de73b
commit b00a42a539
18 changed files with 592 additions and 197 deletions

View File

@@ -189,7 +189,7 @@ struct scc_ast_type {
} enumeration; } enumeration;
struct { struct {
const char *name; const char *name;
scc_ast_type_t *underlying; scc_ast_decl_t *decl;
} typedef_type; } typedef_type;
}; };
}; };

View File

@@ -341,10 +341,33 @@ static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member); _scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member);
} }
// TODO static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
// SCC_AST_EXPR_CAST, // 类型转换 scc_ast_type_t *type,
// SCC_AST_EXPR_SIZE_OF, // sizeof scc_ast_expr_t *operand) {
// SCC_AST_EXPR_ALIGN_OF, // _Alignof Assert(expr != null && type != null && operand != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_CAST;
expr->cast.type = type;
expr->cast.expr = operand;
}
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type) {
Assert(expr != null && type != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_SIZE_OF;
expr->attr_of.type = type;
expr->attr_of.expr = null;
}
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type) {
Assert(expr != null && type != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_SIZE_OF;
expr->attr_of.type = type;
expr->attr_of.expr = null;
}
// init can be null // init can be null
static inline void static inline void
@@ -486,18 +509,18 @@ static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
type->base.type = SCC_AST_TYPE_ENUM; type->base.type = SCC_AST_TYPE_ENUM;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->enumeration.name = name; type->enumeration.name = name;
type->enumeration.decl = null; type->enumeration.decl = decl;
} }
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type, static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_type_t *target) { scc_ast_decl_t *target) {
Assert(type != null && target != null); Assert(type != null && target != null);
type->base.loc = scc_pos_create(); type->base.loc = scc_pos_create();
type->base.type = SCC_AST_TYPE_TYPEDEF; type->base.type = SCC_AST_TYPE_TYPEDEF;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->typedef_type.name = name; type->typedef_type.name = name;
type->typedef_type.underlying = target; type->typedef_type.decl = target;
} }
#endif /* __SCC_AST_H__ */ #endif /* __SCC_AST_H__ */

View File

@@ -567,6 +567,10 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true); dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true);
break; break;
case SCC_AST_STMT_BREAK:
case SCC_AST_STMT_CONTINUE:
break;
case SCC_AST_STMT_DEFAULT: case SCC_AST_STMT_DEFAULT:
end_node_dump(ctx); end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true); dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true);

View File

@@ -71,4 +71,13 @@ static inline void scc_parser_reset(scc_parser_t *parser) {
scc_ring_reset(*parser->ring); scc_ring_reset(*parser->ring);
} }
#include <scc_pos_log.h>
static inline scc_pos_t scc_parser_got_current_pos(scc_parser_t *parser) {
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
scc_pos_t pos = scc_pos_create();
if (tok != null)
pos = tok->loc;
return pos;
}
#endif /* __SCC_PARSER_UTILS_H__ */ #endif /* __SCC_PARSER_UTILS_H__ */

View File

@@ -58,6 +58,8 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser);
* @return 语句 AST 节点 * @return 语句 AST 节点
*/ */
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser); scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser);
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser);
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser);
/** /**
* @brief 解析表达式 * @brief 解析表达式
@@ -75,4 +77,24 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser);
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser); scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser);
static inline void scc_parse_decl_sema(scc_parser_t *parser,
scc_ast_decl_t *decl) {
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
decl ? decl->base.type : SCC_AST_UNKNOWN,
decl);
}
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,
type ? type->base.type : SCC_AST_UNKNOWN,
type);
}
static inline scc_ast_type_t *scc_parse_got_type(scc_parser_t *parser,
const char *name) {
return parser->sema_callbacks.got_type(parser->sema_callbacks.context,
name);
}
#endif /* __SCC_PARSER_H__ */ #endif /* __SCC_PARSER_H__ */

View File

@@ -155,9 +155,6 @@ A.2.4 External definitions
#include <scc_parser.h> #include <scc_parser.h>
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { 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_node_t *type_or_decl = _scc_parse_type(parser);
scc_ast_decl_t *decl = null; scc_ast_decl_t *decl = null;
if (type_or_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)) { } 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); decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
} else { } else {
LOG_ERROR("invalid declaration"); SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
return null; 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); scc_ast_expr_t *init = scc_parse_expression(parser);
decl->var.init = init; decl->var.init = init;
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { 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; goto RETURN;
} else if (tok_ptr->type == SCC_TOK_L_BRACE) { } 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: RETURN:
if (decl) { scc_parse_decl_sema(parser, decl);
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
decl->base.type, decl);
}
return decl; return decl;
} }

View File

@@ -167,8 +167,6 @@ static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser);
// 特殊结构:独立解析(右结合、条件、一元、后缀、基本) // 特殊结构:独立解析(右结合、条件、一元、后缀、基本)
static scc_ast_expr_t * static scc_ast_expr_t *
parse_assignment_expression(scc_parser_t *parser); // 右结合
static scc_ast_expr_t *
parse_conditional_expression(scc_parser_t *parser); // 右结合 parse_conditional_expression(scc_parser_t *parser); // 右结合
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser); // 类型转换 static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser); // 类型转换
static scc_ast_expr_t * 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-expressionC 标准规定赋值左边必须是 // 先解析左侧的 unary-expressionC 标准规定赋值左边必须是
// unary-expression // unary-expression
scc_ast_expr_t *left = null; 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); scc_lexer_tok_drop(&op_tok);
// 解析右侧(右结合:继续调用 parse_assignment_expression // 解析右侧(右结合:继续调用 parse_assignment_expression
scc_ast_expr_t *right = parse_assignment_expression(parser); scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
if (!right) { if (!right) {
// 错误恢复 // 错误恢复
parser_sync(parser); 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)) { 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); parser_sync(parser);
return null; 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) { if (tok && tok->type == SCC_TOK_L_PAREN) {
// 尝试解析类型名 // 尝试解析类型名
scc_parser_store(parser); scc_parser_store(parser);
scc_parser_next(parser);
scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现 scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现
if (type) { if (type) {
// 消耗了类型名后,下一个应该是 ')' // 消耗了类型名后,下一个应该是 ')'
@@ -618,13 +618,12 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
return expr; return expr;
} else { } else {
// 不是类型转换,回退 // 不是类型转换,回退
scc_parser_restore(parser);
// 释放 type假设 scc_parse_type_name 分配了) // 释放 type假设 scc_parse_type_name 分配了)
// TODO: scc_ast_type_drop(type); // TODO: scc_ast_type_drop(type);
} }
} else { } else {
// 解析类型名失败,回退
scc_parser_restore(parser); 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); const scc_lexer_tok_t *next = scc_parser_peek(parser);
if (!next) { if (!next) {
LOG_ERROR("Unexpected end after sizeof"); SCC_ERROR(scc_parser_got_current_pos(parser),
"Unexpected end after sizeof");
return null; return null;
} }
@@ -741,7 +741,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
return null; return null;
} }
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) { 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); parser_sync(parser);
return null; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
while (1) { while (1) {
scc_ast_expr_t *arg = parse_assignment_expression(parser); scc_ast_expr_t *arg =
scc_parse_assignment_expression(parser);
if (!arg) { if (!arg) {
parser_sync(parser); 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)) { } else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
break; break;
} else { } else {
LOG_ERROR("Expected ',' or ')' in function call"); SCC_ERROR(scc_parser_got_current_pos(parser),
"Expected ',' or ')' in function call");
parser_sync(parser); parser_sync(parser);
// 释放资源 // 释放资源
scc_free(call); 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; scc_lexer_tok_t ident_tok;
if (!scc_parser_next_consume(parser, &ident_tok) || if (!scc_parser_next_consume(parser, &ident_tok) ||
ident_tok.type != SCC_TOK_IDENT) { 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); scc_lexer_tok_drop(&op_tok);
parser_sync(parser); parser_sync(parser);
return null; return null;
} }
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme); const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
scc_ast_expr_t *member = expr_create( scc_ast_expr_t *member = expr_create(
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
: SCC_AST_EXPR_PTR_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)) { 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); parser_sync(parser);
return null; 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 *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) if (!left)
return null; return null;
while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) { 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) { if (!right) {
parser_sync(parser); parser_sync(parser);
return null; return null;
@@ -966,3 +972,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
} }
return left; return left;
} }
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
return parse_conditional_expression(parser);
}

View File

@@ -49,6 +49,7 @@ A.2.3 Statements
#include <parser_utils.h> #include <parser_utils.h>
#include <scc_parser.h> #include <scc_parser.h>
static inline scc_ast_stmt_t *ast_stmt_alloc() { 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)); scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t));
if (stmt == null) { 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) { static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { 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); scc_ast_expr_t *ret = scc_parse_expression(parser);
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { 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; return ret;
} }
@@ -97,10 +100,16 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
} }
scc_ast_expr_t *expr = null; 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)) { 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; 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)) { 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; 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); ret = (scc_ast_node_t *)scc_parse_statement(parser);
} }
if (ret == null) { if (ret == null) {
LOG_ERROR("Invalid statement"); SCC_ERROR(scc_parser_got_current_pos(parser), "Invalid statement");
// TODO free // TODO free
parser->errcode = 1; parser->errcode = 1;
return null; 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); scc_ast_stmt_t *statement = scc_parse_statement(parser);
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) { 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 使用更好的错误处理,未来应当采用更好的内存管理器 // TODO 使用更好的错误处理,未来应当采用更好的内存管理器
scc_free(statement); scc_free(statement);
return null; 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)) { 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; 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) { if (init == null) {
init = (scc_ast_type_t *)scc_parse_expression(parser); init = (scc_ast_type_t *)scc_parse_expression(parser);
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { 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); cond = scc_parse_expression(parser);
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { 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); incr = scc_parse_expression(parser);
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { 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); 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)) { 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));
} else { } 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)) { } else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) {
scc_ast_stmt_continue_init(stmt); 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)) { 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; 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); scc_ast_stmt_expr_init(stmt, expr);
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { 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; return stmt;
} }

View File

@@ -212,15 +212,10 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
// 函数说明符 // 函数说明符
case SCC_TOK_INLINE: case SCC_TOK_INLINE:
return true; return true;
// typedef 名称(标识符也可能是类型说明符)
// typedef 名称(标识符也可能是类型说明符)
case SCC_TOK_IDENT: case SCC_TOK_IDENT:
// 需要检查标识符是否在符号表中定义为 typedef return scc_parse_got_type(
// 这里简化处理:假设所有标识符都可能是 typedef parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null;
// 在实际解析器中,需要查询符号表
// TODO
return false;
default: default:
return false; return false;
} }
@@ -250,7 +245,8 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
// typedef 名称 // typedef 名称
case SCC_TOK_IDENT: case SCC_TOK_IDENT:
// 需要检查标识符是否在符号表中定义为 typedef // 需要检查标识符是否在符号表中定义为 typedef
return true; return scc_parse_got_type(
parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null;
default: default:
return false; return false;
} }
@@ -346,50 +342,59 @@ typedef struct {
scc_ast_type_t *user_type; // 如果是用户定义类型,直接存储解析结果 scc_ast_type_t *user_type; // 如果是用户定义类型,直接存储解析结果
} type_spec_info_t; } 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 互斥) // 基本类型不能同时出现多个void, char, int, float, double, bool 互斥)
int basic_count = info->is_void + info->is_char + info->is_short + int basic_count = info->is_void + info->is_char + info->is_short +
info->is_int + info->is_float + info->is_double + info->is_int + info->is_float + info->is_double +
info->is_bool; info->is_bool;
if (basic_count > 1) { if (basic_count > 1) {
LOG_ERROR("Multiple basic type specifiers"); SCC_ERROR(scc_parser_got_current_pos(parser),
"Multiple basic type specifiers");
return false; return false;
} }
// long 不能与 void/char/float/bool 组合(但可以和 double 组合为 long // long 不能与 void/char/float/bool 组合(但可以和 double 组合为 long
// double // double
if (info->is_long && info->is_float) { 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; return false;
} }
if (info->is_long && info->is_char) { 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; return false;
} }
if (info->is_long && info->is_bool) { 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; return false;
} }
// long 与 double 可以组合为 long double // long 与 double 可以组合为 long double
if (info->is_long_long && info->is_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; return false;
} }
// short 只能与 int 组合(默认 int不能与 double/float 等 // short 只能与 int 组合(默认 int不能与 double/float 等
if (info->is_short && if (info->is_short &&
(info->is_double || info->is_float || info->is_bool || info->is_void)) { (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; return false;
} }
// _Complex 只能与 float/double/long double 组合或单独出现C99 中 // _Complex 只能与 float/double/long double 组合或单独出现C99 中
// _Complex 本身不是类型,必须跟浮点类型) // _Complex 本身不是类型,必须跟浮点类型)
if (info->is_complex && !info->is_float && !info->is_double) { 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; return false;
} }
// 如果用户定义了类型struct/typedef不能与任何其他类型说明符混合 // 如果用户定义了类型struct/typedef不能与任何其他类型说明符混合
if (info->user_type != null && basic_count > 0) { 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"); "Cannot combine user-defined type with basic type specifiers");
return false; return false;
} }
@@ -511,7 +516,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
while (1) { while (1) {
tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) { 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; break;
} }
@@ -532,7 +538,8 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
break; break;
} else { } 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); scc_parser_next_consume(parser, null);
break; break;
} }
@@ -545,6 +552,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
} else { } else {
scc_ast_decl_union_init(decl, name, &member); scc_ast_decl_union_init(decl, name, &member);
} }
scc_parse_decl_sema(parser, decl);
} }
scc_ast_type_t *type = ast_type_alloc(); 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 enumeration-constant = constant-expression
*/ */
if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) { 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; return null;
} }
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); 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) { while (1) {
tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) { 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; break;
} }
scc_ast_expr_t *expr = scc_parse_expression(parser); scc_ast_expr_t *expr = scc_parse_assignment_expression(parser);
if (expr != null) { if (expr != null) {
scc_vec_push(member, expr); scc_vec_push(member, expr);
continue; continue;
@@ -606,7 +615,8 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
break; break;
} else { } 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); scc_parser_next_consume(parser, null);
break; 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)); decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null); Assert(decl != null);
scc_ast_decl_enum_init(decl, name, &member); scc_ast_decl_enum_init(decl, name, &member);
scc_parse_decl_sema(parser, decl);
} }
scc_ast_type_t *type = ast_type_alloc(); 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}; type_spec_info_t info = {0};
if (!scc_parse_is_type_specifier_start(parser)) if (!scc_parse_is_type_specifier_start(parser))
return null; 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) { while (1) {
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) { if (tok_ptr == null) {
break; break;
} }
@@ -658,7 +697,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
case SCC_TOK_LONG: case SCC_TOK_LONG:
// long 可以出现两次 // long 可以出现两次
if (info.is_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; return null;
} }
if (info.is_long) { if (info.is_long) {
@@ -689,7 +729,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
break; break;
case SCC_TOK_SIGNED: case SCC_TOK_SIGNED:
if (info.is_unsigned || info.is_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; return null;
} }
info.is_signed = true; info.is_signed = true;
@@ -697,7 +738,8 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
break; break;
case SCC_TOK_UNSIGNED: case SCC_TOK_UNSIGNED:
if (info.is_unsigned || info.is_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; return null;
} }
info.is_unsigned = true; info.is_unsigned = true;
@@ -709,41 +751,28 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
info.is_complex = true; info.is_complex = true;
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
break; 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: default:
goto done; goto done;
} }
} }
done: done:
if (!check_type_combinations(&info)) { if (!check_type_combinations(parser, &info)) {
return null; return null;
} }
return build_type_from_info(&info); return build_type_from_info(&info);
duplicate_error: duplicate_error:
LOG_ERROR("Duplicate type specifier"); SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
return null; 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 *base,
scc_ast_type_t **delay_pointee_ptr); scc_ast_type_t **delay_pointee_ptr,
static scc_ast_node_t * scc_lexer_tok_t *tok_ident);
static scc_ast_type_t *
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, 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 * static scc_ast_type_t *
parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
scc_ast_type_t **delay_pointee_ptr); 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; scc_ast_decl_t *param = null;
while (1) { while (1) {
// FIXME // FIXME
scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser); scc_ast_node_t *node = _scc_parse_type(parser);
scc_ast_type_t *type = parse_type_specifier(parser); if (node == null) {
if (type == null) { return;
break;
} }
type->quals = spec;
scc_ast_node_t *node = parse_declarator(parser, type, null);
if (SCC_AST_IS_A(scc_ast_decl_t, node)) { if (SCC_AST_IS_A(scc_ast_decl_t, node)) {
param = SCC_AST_CAST_TO(scc_ast_decl_t, node); param = SCC_AST_CAST_TO(scc_ast_decl_t, node);
// TODO Check validation // TODO Check validation
Assert(param->base.type = SCC_AST_DECL_VAR);
param->base.type = SCC_AST_DECL_PARAM; param->base.type = SCC_AST_DECL_PARAM;
} else if (SCC_AST_IS_A(scc_ast_type_t, node)) { } else if (SCC_AST_IS_A(scc_ast_type_t, node)) {
param = scc_malloc(sizeof(scc_ast_decl_t)); 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, static void parse_function_parameters(scc_parser_t *parser,
scc_ast_decl_vec_t *params) { scc_ast_decl_vec_t *params) {
// FIXME ? // FIXME ?
// if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { // 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); scc_vec_init(*params);
parse_parameter_type_list(parser, params); parse_parameter_type_list(parser, params);
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { 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) { static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
const scc_lexer_tok_t *tok_ptr = null; const scc_lexer_tok_t *tok_ptr = null;
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) { 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; parser->errcode = 1;
return null; 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)) { 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; parser->errcode = 1;
return null; return null;
} }
return size; 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 *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: (6.7.5) declarator:
pointer(opt) direct-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) ) direct-declarator ( identifier-list(opt) )
*/ */
scc_ast_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); 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, 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; const scc_lexer_tok_t *tok_ptr = null;
scc_ast_type_t *ret = null; scc_ast_type_t *ret = null;
// direct-abstract-declarator // direct-abstract-declarator
tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) { if (tok_ptr == null) {
return (scc_ast_node_t *)base; return base;
} }
if (tok_ptr->type == SCC_TOK_IDENT) { if (tok_ptr->type == SCC_TOK_IDENT) {
scc_lexer_tok_t tok = {0}; Assert(tok_ident != null);
scc_parser_next_consume(parser, &tok); if (tok_ident->type != SCC_TOK_UNKNOWN) {
SCC_ERROR(scc_parser_got_current_pos(parser),
scc_ast_node_t *type = "Got double identifier in declarator");
parse_direct_declarator(parser, base, delay_pointee_ptr); return base;
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);
} }
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) { } else if (tok_ptr->type == SCC_TOK_L_PAREN) {
// () SCC_TOK_L_PAREN // () SCC_TOK_L_PAREN
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
scc_ast_type_t *delay_pointee = null; scc_ast_type_t *delay_pointee = null;
ret = parse_abstract_declarator(parser, null, &delay_pointee); if (parse_function_parameters_start(parser)) {
if (ret == null) {
scc_ast_decl_vec_t params; scc_ast_decl_vec_t params;
parse_function_parameters(parser, &params); parse_function_parameters(parser, &params);
ret = ast_type_alloc(); ret = ast_type_alloc();
scc_ast_type_function_init(ret, base, &params); scc_ast_type_function_init(ret, base, &params);
return (scc_ast_node_t *)parse_direct_declarator(parser, ret, return parse_direct_declarator(parser, ret, delay_pointee_ptr,
delay_pointee_ptr); tok_ident);
} else { } else {
ret = parse_declarator(parser, null, &delay_pointee, tok_ident);
Assert(ret != null);
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { 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, base = parse_direct_declarator(parser, base, delay_pointee_ptr,
delay_pointee_ptr); tok_ident);
Assert(SCC_AST_IS_A(scc_ast_type_t, base)); Assert(SCC_AST_IS_A(scc_ast_type_t, base));
Assert(delay_pointee != null); Assert(delay_pointee != null);
delay_pointee->pointer.pointee = base; delay_pointee->pointer.pointee = base;
return ret;
} }
return (scc_ast_node_t *)ret;
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) { } else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
// [] SCC_TOK_L_BRACKET // [] SCC_TOK_L_BRACKET
scc_ast_expr_t *size = parse_array_size_type(parser); scc_ast_expr_t *size = parse_array_size_type(parser);
scc_ast_type_t *ret = ast_type_alloc(); scc_ast_type_t *ret = ast_type_alloc();
base = (scc_ast_type_t *)parse_direct_declarator(parser, base, base =
delay_pointee_ptr); parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
Assert(SCC_AST_IS_A(scc_ast_type_t, base));
scc_ast_type_array_init(ret, base, size); scc_ast_type_array_init(ret, base, size);
return (scc_ast_node_t *)ret; return ret;
} else { } 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_TOK_L_PAREN
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
scc_ast_type_t *delay_pointee = null; scc_ast_type_t *delay_pointee = null;
ret = parse_abstract_declarator(parser, null, &delay_pointee); if (parse_function_parameters_start(parser)) {
if (ret == null) {
scc_ast_decl_vec_t params; scc_ast_decl_vec_t params;
parse_function_parameters(parser, &params); parse_function_parameters(parser, &params);
ret = ast_type_alloc(); 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, return parse_direct_abstract_declarator(parser, ret,
delay_pointee_ptr); delay_pointee_ptr);
} else { } else {
ret = parse_abstract_declarator(parser, null, &delay_pointee);
Assert(ret != null);
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { 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, base = parse_direct_abstract_declarator(parser, base,
delay_pointee_ptr); delay_pointee_ptr);
@@ -1055,12 +1091,33 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
if (ret != null) { if (ret != null) {
ret->quals = spec; ret->quals = spec;
} }
scc_ast_node_t *node = parse_declarator(parser, ret, null);
if (is_typedef_decl) { scc_lexer_tok_t tok_ident = {0};
Assert(node->type == SCC_AST_DECL_VAR); scc_ast_type_t *type = parse_declarator(parser, ret, null, &tok_ident);
node->type = SCC_AST_DECL_TYPEDEF;
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) { scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {

View File

@@ -1,5 +1,6 @@
#include <parser_utils.h> #include <parser_utils.h>
#include <scc_parser.h> #include <scc_parser.h>
static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type, static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
void *node) { void *node) {
(void)context; (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); scc_vec_push(unit->declarations, decl);
} else { } else {
break; break;
// MAYBE return or next
} }
if (parser->errcode != 0) { // FIXME errcode if (parser->errcode != 0) { // FIXME errcode
SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d",
parser->errcode);
break; break;
} }
const scc_lexer_tok_t *tok = scc_parser_peek(parser); 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) { if (parser->errcode) {
// TODO: 清理 // TODO: 清理
SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d",
parser->errcode);
scc_free(unit); scc_free(unit);
return null; return null;
} }

View File

@@ -1,6 +1,55 @@
#include <scc_sema.h> #include <scc_sema.h>
#include <sema_symtab.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) { void scc_sema_init(scc_sema_callbacks_t *callbacks) {
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t)); scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
if (sema_symtab == null) { if (sema_symtab == null) {
@@ -8,11 +57,19 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
return; return;
} }
callbacks->context = sema_symtab; callbacks->context = sema_symtab;
callbacks->on_decl = null; callbacks->on_decl = decl_callback;
callbacks->on_expr = null; callbacks->on_expr = null;
callbacks->on_stmt = null; callbacks->on_stmt = null;
callbacks->on_type = null; callbacks->on_type = type_callback;
callbacks->got_type = null; 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) {} void scc_sema_drop(scc_sema_callbacks_t *callbacks) {}

View File

@@ -4,8 +4,8 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
symtab->root_scope.parent = null; symtab->root_scope.parent = null;
scc_hashtable_init(&symtab->root_scope.symbols, scc_hashtable_init(&symtab->root_scope.symbols,
(scc_hashtable_hash_func_t)scc_strcmp, (scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strhash32); (scc_hashtable_equal_func_t)scc_strcmp);
symtab->current_scope = &symtab->root_scope; symtab->current_scope = &symtab->root_scope;
} }

View File

@@ -7,7 +7,8 @@
typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser);
static scc_ast_node_t *process_input(const char *input, static scc_ast_node_t *process_input(const char *input,
scc_parse_node_func parse_func) { scc_parse_node_func parse_func,
cbool need_sema) {
int res = 0; int res = 0;
scc_sstream_t mem_stream; scc_sstream_t mem_stream;
res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false,
@@ -20,7 +21,13 @@ static scc_ast_node_t *process_input(const char *input,
scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false);
scc_parser_t parser; scc_parser_t parser;
scc_parser_init(&parser, tok_ring, null); if (need_sema) {
scc_sema_callbacks_t sema_callbacks;
scc_sema_init(&sema_callbacks);
scc_parser_init(&parser, tok_ring, &sema_callbacks);
} else {
scc_parser_init(&parser, tok_ring, null);
}
scc_ast_node_t *ret = parse_func(&parser); scc_ast_node_t *ret = parse_func(&parser);
@@ -55,8 +62,8 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
} }
static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str,
scc_parse_node_func parse_func) { scc_parse_node_func parse_func, cbool need_sema) {
scc_ast_node_t *output_node_ptr = process_input(str, parse_func); scc_ast_node_t *output_node_ptr = process_input(str, parse_func, need_sema);
scc_tree_dump_ctx_t ctx; scc_tree_dump_ctx_t ctx;
expect_buffer[0] = '\n', expect_buffer[1] = '\0'; expect_buffer[0] = '\n', expect_buffer[1] = '\0';
scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer);
@@ -68,9 +75,19 @@ static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str,
scc_tree_dump_ctx_drop(&ctx); scc_tree_dump_ctx_drop(&ctx);
} }
#define SCC_CHECK_AST_WITH_SEMA(expect_node_ptr, str, parse_func) \
do { \
_scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \
true); \
TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \
TEST_MSG("Expected: %s", expect_buffer); \
TEST_MSG("Produced: %s", output_buffer); \
} while (0);
#define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ #define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \
do { \ do { \
_scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func); \ _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \
false); \
TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \
TEST_MSG("Expected: %s", expect_buffer); \ TEST_MSG("Expected: %s", expect_buffer); \
TEST_MSG("Produced: %s", output_buffer); \ TEST_MSG("Produced: %s", output_buffer); \
@@ -370,8 +387,38 @@ static void test_parser_unit(void) {
scc_ast_decl_t typedef_decl; scc_ast_decl_t typedef_decl;
scc_ast_decl_typedef_init(&typedef_decl, "int32_t", scc_ast_decl_typedef_init(&typedef_decl, "int32_t",
&scc_ast_builtin_type_int); &scc_ast_builtin_type_int);
SCC_CHECK_AST(&typedef_decl.base, "typedef int int32_t;", scc_ast_type_t typedef_type;
scc_parse_declaration); scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl);
scc_ast_decl_t i32a_decl;
scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null);
scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base};
scc_ast_stmt_t stmt;
scc_ast_block_item_vec_t items;
scc_vec_unsafe_from_array(items, array);
scc_ast_stmt_compound_init(&stmt, &items);
SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef int int32_t;int32_t a;}",
scc_parse_statement);
scc_ast_type_t void_ptr;
scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void);
scc_ast_decl_t void_ptr_decl;
scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr);
scc_ast_type_t void_ptr_type;
scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl);
scc_ast_decl_t void_ptr_a_decl;
scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null);
scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base};
scc_vec_unsafe_from_array(items, array2);
scc_ast_stmt_compound_init(&stmt, &items);
SCC_CHECK_AST_WITH_SEMA(&stmt.base,
"{typedef void* void_ptr; void_ptr a;}",
scc_parse_statement);
SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, "typedef void *void_ptr;",
scc_parse_declaration);
} }
{ {
@@ -387,6 +434,145 @@ static void test_parser_unit(void) {
scc_ast_decl_struct_init(&struct_def, null, &fields); scc_ast_decl_struct_init(&struct_def, null, &fields);
SCC_CHECK_AST(&struct_def.base, "struct { int x; };", SCC_CHECK_AST(&struct_def.base, "struct { int x; };",
scc_parse_declaration); scc_parse_declaration);
scc_ast_type_t struct_type;
scc_ast_type_struct_init(&struct_type, null, &struct_def);
scc_ast_type_t typedef_type;
scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def);
scc_ast_decl_t typedef_decl;
scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type);
SCC_CHECK_AST_WITH_SEMA(&typedef_decl.base,
"typedef struct { int x; } struct_t;",
scc_parse_declaration);
scc_ast_decl_t typedef_impl_decl;
scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null);
scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base};
scc_ast_stmt_t stmt;
scc_ast_block_item_vec_t items;
scc_vec_unsafe_from_array(items, array);
scc_ast_stmt_compound_init(&stmt, &items);
SCC_CHECK_AST_WITH_SEMA(
&stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}",
scc_parse_statement);
}
{
scc_ast_decl_t type_decl;
scc_ast_decl_typedef_init(&type_decl, "size_t",
&scc_ast_builtin_type_long_long);
scc_ast_type_t type_type;
scc_ast_type_typedef_init(&type_type, "size_t", &type_decl);
scc_ast_decl_t param1;
scc_ast_decl_param_init(&param1, &type_type, "a");
scc_ast_decl_t param2;
scc_ast_decl_param_init(&param2, &scc_ast_builtin_type_int, "b");
scc_ast_decl_t param3;
scc_ast_decl_param_init(&param3, &scc_ast_builtin_type_va_list, null);
scc_ast_decl_t *params_array[] = {&param1, &param2, &param3};
scc_ast_decl_vec_t func_params;
scc_vec_unsafe_from_array(func_params, params_array);
scc_ast_type_t func_type;
scc_ast_type_t return_type;
scc_ast_type_pointer_init(&return_type, &scc_ast_builtin_type_void);
scc_ast_type_function_init(&func_type, &return_type, &func_params);
scc_ast_decl_t func_decl;
scc_ast_decl_func_init(&func_decl, &func_type, "func", null);
scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl};
scc_ast_translation_unit_t tu;
scc_ast_decl_vec_t decls;
scc_vec_unsafe_from_array(decls, decls_array);
scc_ast_translation_unit_init(&tu, &decls);
SCC_CHECK_AST_WITH_SEMA(&tu.base,
"typedef long long size_t;"
"void *func(size_t a, int b, ...);",
scc_parse_translation_unit);
scc_ast_type_t type_func_ptr_type;
scc_ast_type_pointer_init(&type_func_ptr_type, &func_type);
scc_ast_decl_t type_func_ptr_decl;
scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t",
&type_func_ptr_type);
scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl};
scc_vec_unsafe_from_array(decls, decls_array2);
scc_ast_translation_unit_init(&tu, &decls);
SCC_CHECK_AST_WITH_SEMA(
&tu.base,
"typedef long long size_t;"
"typedef void *(*func_t)(size_t a, int b, ...);",
scc_parse_translation_unit);
}
{
// int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针)
// 步骤:
// 1) 数组类型int [5]
scc_ast_expr_t size_5;
scc_ast_expr_literal_int_init(&size_5, "5", false);
scc_ast_type_t array_of_5_int;
scc_ast_type_array_init(&array_of_5_int,
(scc_ast_type_t *)&scc_ast_builtin_type_int,
&size_5);
// 2) 函数类型:返回指向数组的指针,无参数
scc_ast_type_t ptr_to_array;
scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int);
scc_ast_type_t func_type;
scc_ast_decl_vec_t func_params;
scc_ast_decl_t void_decl;
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
scc_ast_decl_t *array[] = {&void_decl};
scc_vec_unsafe_from_array(func_params, array);
scc_ast_type_function_init(&func_type, &ptr_to_array,
&func_params); // 无参数
// 3) 指向该函数的指针
scc_ast_type_t ptr_to_func;
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
scc_ast_decl_t ptr_to_func_decl;
scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null);
SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];",
scc_parse_declaration);
scc_ast_decl_t typedef_func_decl;
scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func);
scc_ast_type_t typedef_func_type;
scc_ast_type_typedef_init(&typedef_func_type, "func_t",
&typedef_func_decl);
scc_ast_decl_t func_hard_decl;
scc_ast_type_t func_hard_type;
scc_ast_decl_t param1;
scc_ast_decl_param_init(&param1, &ptr_to_func, "bar");
scc_ast_decl_t param2;
scc_ast_decl_param_init(&param2, &typedef_func_type, "a");
scc_ast_decl_t param3;
scc_ast_decl_param_init(&param1, &scc_ast_builtin_type_va_list, null);
scc_ast_decl_t *func_hard_array[] = {&param1, &param2, &param3};
scc_ast_decl_vec_t func_hard_params;
scc_vec_unsafe_from_array(func_hard_params, func_hard_array);
scc_ast_type_function_init(&func_hard_type, &ptr_to_array,
&func_hard_params);
scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null);
scc_ast_decl_vec_t decls;
scc_ast_decl_t *decls_array[] = {
&typedef_func_decl,
&func_hard_decl,
};
scc_vec_unsafe_from_array(decls, decls_array);
scc_ast_translation_unit_t tu;
scc_ast_translation_unit_init(&tu, &decls);
// SCC_CHECK_AST_WITH_SEMA(
// &tu.base,
// "typedef int (*(*func_t)(void))[5];"
// "int (*(*(bar)(int(*(*foo)(void))[5], func_t a,
// ...))(void))[5];", scc_parse_translation_unit);
} }
} }
@@ -513,18 +699,12 @@ static void test_parser_expression(void) {
// 4. 类型转换(示例: (int)x // 4. 类型转换(示例: (int)x
{ {
// scc_ast_type_t scc_ast_expr_t x;
// int_type; // 使用内置类型全局变量即可,但类型转换需要一个类型节点 scc_ast_expr_identifier_init(&x, "x");
// // scc_ast_expr_t cast;
// 我们可以直接使用全局内置类型的地址,但类型转换节点需要一个类型节点,直接引用全局即可 scc_ast_expr_cast_init(&cast,
// // TODO (scc_ast_type_t *)&scc_ast_builtin_type_int, &x);
// scc_ast_expr_t x; SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression);
// scc_ast_expr_identifier_init(&x, "x");
// scc_ast_expr_t cast;
// scc_ast_expr_cast_init(&cast,
// (scc_ast_type_t *)&scc_ast_builtin_type_int,
// &x);
// SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression);
} }
// 5. 二元运算符优先级 // 5. 二元运算符优先级
@@ -1168,10 +1348,8 @@ static void test_parser_type(void) {
scc_ast_expr_identifier_init(&green, "GREEN"); scc_ast_expr_identifier_init(&green, "GREEN");
scc_ast_expr_identifier_init(&blue, "BLUE"); scc_ast_expr_identifier_init(&blue, "BLUE");
scc_ast_expr_vec_t enumerators; scc_ast_expr_vec_t enumerators;
scc_vec_init(enumerators); scc_ast_expr_t *array[] = {&red, &green, &blue};
scc_vec_push(enumerators, &red); scc_vec_unsafe_from_array(enumerators, array);
scc_vec_push(enumerators, &green);
scc_vec_push(enumerators, &blue);
scc_ast_decl_t enum_def; scc_ast_decl_t enum_def;
scc_ast_decl_enum_init(&enum_def, null, &enumerators); scc_ast_decl_enum_init(&enum_def, null, &enumerators);
@@ -1179,9 +1357,11 @@ static void test_parser_type(void) {
scc_ast_type_enum_init(&enum_type, null, &enum_def); scc_ast_type_enum_init(&enum_type, null, &enum_def);
SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }",
_scc_parse_type); _scc_parse_type);
scc_vec_unsafe_from_array(enumerators, array);
scc_ast_decl_enum_init(&enum_def, "E", &enumerators); scc_ast_decl_enum_init(&enum_def, "E", &enumerators);
scc_ast_type_enum_init(&enum_type, "E", &enum_def); scc_ast_type_enum_init(&enum_type, "E", &enum_def);
SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE }", SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }",
_scc_parse_type); _scc_parse_type);
} }

View File

@@ -90,6 +90,10 @@ static inline void fill_replacements(scc_pproc_t *pp,
scc_ring_next_consume(*pp->cur_ring, tok, ok); scc_ring_next_consume(*pp->cur_ring, tok, ok);
if (!ok) if (!ok)
break; break;
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_COMMENT) {
scc_lexer_tok_drop(&tok);
continue;
}
if (tok.type == SCC_TOK_EOF || tok.type == SCC_TOK_ENDLINE) { if (tok.type == SCC_TOK_EOF || tok.type == SCC_TOK_ENDLINE) {
scc_lexer_tok_drop(&tok); scc_lexer_tok_drop(&tok);
break; break;

View File

@@ -96,10 +96,10 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros,
scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp, scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp,
scc_pproc_macro_t *macro) { scc_pproc_macro_t *macro) {
Assert(pp != null && macro != null); Assert(pp != null && macro != null && scc_cstring_len(&macro->name) != 0);
scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, &macro->name, macro); scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, &macro->name, macro);
if (old && old != macro) { if (old && old != macro) {
LOG_WARN("same macro name"); LOG_WARN("same macro name `%s`", scc_cstring_as_cstr(&macro->name));
scc_pproc_macro_drop(old); scc_pproc_macro_drop(old);
} }
return macro; return macro;

View File

@@ -194,6 +194,11 @@ static void test_define_nested_macros(void) {
CHECK_PP_OUTPUT_EXACT("#define default a\n" CHECK_PP_OUTPUT_EXACT("#define default a\n"
"default\n", "default\n",
"a\n"); "a\n");
TEST_CASE("test_macro_end_by_comment");
CHECK_PP_OUTPUT_EXACT("#define MAX_SIZE 128///! COMMENT\n"
"MAX_SIZE\n",
"128\n");
} }
static void test_undef_macros(void) { static void test_undef_macros(void) {

View File

@@ -34,25 +34,29 @@ static_assert(sizeof(cbool) == 1, "cbool size must 1");
#else #else
/* clang-format off */ /* clang-format off */
typedef __scc_i8 i8;
typedef __scc_i16 i16;
typedef __scc_i32 i32;
typedef __scc_i64 i64;
typedef __scc_u8 u8;
typedef __scc_u16 u16;
typedef __scc_u32 u32;
typedef __scc_u64 u64;
typedef __scc_isize isize; #include <stdarg.h>
typedef __scc_usize usize; #include <stdbool.h>
typedef __scc_isize pdiff; #include <stddef.h>
#include <stdint.h>
typedef __scc_f32 f32; typedef int8_t i8;
typedef __scc_f64 f64; typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef __scc_bool cbool; typedef intptr_t isize;
/// void / null typedef uintptr_t usize;
#define null __scc_null typedef ptrdiff_t pdiff;
typedef float f32;
typedef double f64;
typedef bool cbool;
/* clang-format on */ /* clang-format on */
#endif #endif

View File

@@ -10,6 +10,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __SCC__ // FIXME it will be remove
typedef void *FILE;
#endif
void *scc_pal_malloc(size_t size) { return malloc(size); } void *scc_pal_malloc(size_t size) { return malloc(size); }
void *scc_pal_calloc(size_t count, size_t size) { return calloc(count, size); } void *scc_pal_calloc(size_t count, size_t size) { return calloc(count, size); }