feat(ast): 添加内置类型定义和AST节点初始化函数
添加了完整的内置类型支持,包括整数、浮点数、字符、布尔等基本类型, 以及它们的有符号/无符号变体。同时添加了大量的AST节点初始化函数, 简化了AST节点的创建过程。 BREAKING CHANGE: 重构了AST表达式和声明结构,移除了冗余字段, 统一了命名规范,并修改了函数调用和成员访问的表示方式。
This commit is contained in:
@@ -188,7 +188,6 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
|
||||
/*
|
||||
(6.7.5) declarator:
|
||||
pointeropt direct-declarator
|
||||
@@ -203,18 +202,14 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
direct-declarator ( identifier-listopt )
|
||||
*/
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
// TODO
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->var.type = type;
|
||||
decl->var.name = scc_cstring_as_cstr(&tok.lexeme);
|
||||
decl->var.init = null;
|
||||
scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
|
||||
null);
|
||||
goto RETURN;
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->var.type = type;
|
||||
decl->var.name = scc_cstring_as_cstr(&tok.lexeme);
|
||||
decl->var.init = scc_parse_expression(parser);
|
||||
scc_ast_expr_t *init = scc_parse_expression(parser);
|
||||
scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
|
||||
init);
|
||||
goto RETURN;
|
||||
}
|
||||
// TODO
|
||||
@@ -223,13 +218,11 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
|
||||
// function decl
|
||||
decl->base.type = SCC_AST_DECL_FUNC;
|
||||
decl->func.name = scc_cstring_as_cstr(&tok.lexeme);
|
||||
decl->name = scc_cstring_as_cstr(&tok.lexeme);
|
||||
decl->func.type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
decl->func.type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||
scc_vec_init(decl->func.type->function.param_types);
|
||||
decl->func.type->function.return_type = type;
|
||||
// TODO
|
||||
decl->func.type->function.is_variadic = false;
|
||||
|
||||
// TODO param type
|
||||
scc_parser_consume_if(parser, SCC_TOK_VOID);
|
||||
|
||||
@@ -760,7 +760,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_drop(&lp);
|
||||
|
||||
scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL);
|
||||
call->call.callee = left;
|
||||
call->call._target = left;
|
||||
scc_vec_init(call->call.args);
|
||||
|
||||
// 解析参数列表
|
||||
@@ -811,13 +811,9 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *member = expr_create(
|
||||
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
|
||||
: SCC_AST_EXPR_PTR_MEMBER);
|
||||
if (op_tok.type == SCC_TOK_DOT) {
|
||||
member->member.base = left;
|
||||
member->member.member_name = name;
|
||||
} else {
|
||||
member->ptr_member.base = left;
|
||||
member->ptr_member.member_name = name;
|
||||
}
|
||||
member->member.base = left;
|
||||
member->member.name = name;
|
||||
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
left = member;
|
||||
break;
|
||||
|
||||
@@ -51,9 +51,9 @@ A.2.3 Statements
|
||||
#include <scc_parser.h>
|
||||
static inline scc_ast_stmt_t *ast_stmt_alloc() {
|
||||
scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t));
|
||||
Assert(stmt != null);
|
||||
stmt->base.type = SCC_AST_UNKNOWN;
|
||||
stmt->base.loc = scc_pos_create();
|
||||
if (stmt == null) {
|
||||
LOG_FATAL("Out of memory");
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -87,10 +87,7 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
|
||||
stmt->base.type = SCC_AST_STMT_LABEL;
|
||||
stmt->label_stmt.label = scc_cstring_as_cstr(&tok.lexeme);
|
||||
stmt->label_stmt.stmt = statement;
|
||||
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -113,10 +110,7 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
stmt->case_stmt.expr = expr;
|
||||
stmt->base.type = SCC_AST_STMT_CASE;
|
||||
stmt->case_stmt.stmt = statement;
|
||||
scc_ast_stmt_case_init(stmt, expr, statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -134,11 +128,9 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
if (statement == null) {
|
||||
Panic("expect stmt");
|
||||
}
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
stmt->base.type = SCC_AST_STMT_DEFAULT;
|
||||
stmt->default_stmt.stmt = statement;
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_default_init(stmt, statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -146,10 +138,9 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||
return null;
|
||||
}
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
stmt->base.type = SCC_AST_STMT_COMPOUND;
|
||||
scc_ast_block_item_vec_t block_items;
|
||||
scc_vec_init(block_items);
|
||||
|
||||
scc_vec_init(stmt->compound.block_items);
|
||||
while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
|
||||
/// TODO
|
||||
// scc_parse_is_decl();
|
||||
@@ -160,12 +151,15 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
}
|
||||
if (ret == null) {
|
||||
LOG_ERROR("Invalid statement");
|
||||
// TODO
|
||||
scc_free(stmt);
|
||||
// TODO free
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
}
|
||||
scc_vec_push(stmt->compound.block_items, ret);
|
||||
scc_vec_push(block_items, ret);
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_compound_init(stmt, &block_items);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -176,16 +170,16 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
scc_ast_stmt_t *opt_else = null;
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ELSE)) {
|
||||
opt_else = scc_parse_statement(parser);
|
||||
} else {
|
||||
opt_else = null;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
stmt->base.type = SCC_AST_STMT_IF;
|
||||
stmt->if_stmt.cond = expression;
|
||||
stmt->if_stmt.then_stmt = statement;
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ELSE)) {
|
||||
stmt->if_stmt.opt_else_stmt = scc_parse_statement(parser);
|
||||
} else {
|
||||
stmt->if_stmt.opt_else_stmt = null;
|
||||
}
|
||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -198,9 +192,7 @@ 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();
|
||||
stmt->base.type = SCC_AST_STMT_SWITCH;
|
||||
stmt->switch_stmt.cond = expression;
|
||||
stmt->switch_stmt.body = statement;
|
||||
scc_ast_stmt_switch_init(stmt, expression, statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -213,9 +205,7 @@ 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();
|
||||
stmt->base.type = SCC_AST_STMT_WHILE;
|
||||
stmt->while_stmt.cond = expression;
|
||||
stmt->while_stmt.body = statement;
|
||||
scc_ast_stmt_while_init(stmt, expression, statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -235,9 +225,7 @@ 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();
|
||||
stmt->base.type = SCC_AST_STMT_DO_WHILE;
|
||||
stmt->do_while_stmt.cond = expression;
|
||||
stmt->do_while_stmt.body = statement;
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -255,15 +243,17 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
LOG_ERROR("Expected '(' before like `( expression )` .");
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
stmt->base.type = SCC_AST_STMT_FOR;
|
||||
scc_ast_type_t *init = null;
|
||||
scc_ast_expr_t *cond = null;
|
||||
scc_ast_expr_t *incr = null;
|
||||
scc_ast_stmt_t *body = null;
|
||||
|
||||
// TODO use decl or expr
|
||||
stmt->for_stmt.init = (scc_ast_type_t *)scc_parse_expression(parser);
|
||||
if (stmt->for_stmt.init == null) {
|
||||
stmt->for_stmt.init = (scc_ast_type_t *)scc_parse_declaration(parser);
|
||||
init = (scc_ast_type_t *)scc_parse_expression(parser);
|
||||
if (init == null) {
|
||||
init = (scc_ast_type_t *)scc_parse_declaration(parser);
|
||||
}
|
||||
if (stmt->for_stmt.init == null) {
|
||||
if (init == null) {
|
||||
LOG_ERROR("Expected expression or declaration in for statement.");
|
||||
}
|
||||
|
||||
@@ -271,20 +261,22 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
LOG_ERROR("Expected semicolon in for statement.");
|
||||
}
|
||||
|
||||
stmt->for_stmt.cond = scc_parse_expression(parser);
|
||||
cond = scc_parse_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon in for statement.");
|
||||
}
|
||||
|
||||
stmt->for_stmt.iter = scc_parse_expression(parser);
|
||||
incr = scc_parse_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_ERROR("Expected ')' after like `( expression )` .");
|
||||
}
|
||||
|
||||
stmt->for_stmt.body = scc_parse_statement(parser);
|
||||
body = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_for_init(stmt, init, cond, incr, body);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -292,20 +284,18 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
||||
stmt->base.type = SCC_AST_STMT_GOTO;
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (scc_parser_next_consume(parser, &tok)) {
|
||||
stmt->goto_stmt.label = scc_cstring_as_cstr(&tok.lexeme);
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme));
|
||||
} else {
|
||||
LOG_ERROR("Expected label after goto.");
|
||||
}
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) {
|
||||
stmt->base.type = SCC_AST_STMT_CONTINUE;
|
||||
scc_ast_stmt_continue_init(stmt);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_BREAK)) {
|
||||
stmt->base.type = SCC_AST_STMT_BREAK;
|
||||
scc_ast_stmt_break_init(stmt);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_RETURN)) {
|
||||
stmt->base.type = SCC_AST_STMT_RETURN;
|
||||
stmt->return_stmt.expr = scc_parse_expression(parser);
|
||||
scc_ast_stmt_return_init(stmt, scc_parse_expression(parser));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -317,21 +307,19 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
stmt->base.type = SCC_AST_STMT_EXPR;
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
stmt->expr.expr = null;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
stmt->expr.expr = scc_parse_expression(parser);
|
||||
if (stmt->expr.expr == null) {
|
||||
// TODO
|
||||
scc_free(stmt);
|
||||
return null;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_parse_expression(parser);
|
||||
if (expr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, expr);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("Expected semicolon after expression.");
|
||||
}
|
||||
|
||||
@@ -234,7 +234,11 @@ cbool scc_parse_is_storage_class_start(scc_parser_t *parser) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
scc_ast_type_t *scc_parse_type(scc_parser_t *parser) {
|
||||
if (!scc_parse_is_decl_specifier_start(parser)) {
|
||||
return null;
|
||||
}
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_type_t *ret = null;
|
||||
if (tok_ptr->type == SCC_TOK_INT) {
|
||||
|
||||
@@ -17,7 +17,7 @@ static scc_ast_node_t *process_input(const char *input,
|
||||
scc_lexer_t lexer;
|
||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream));
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 8, false);
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false);
|
||||
|
||||
scc_parser_t parser;
|
||||
scc_parser_init(&parser, tok_ring, null);
|
||||
@@ -69,516 +69,455 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
|
||||
} while (0);
|
||||
|
||||
static void test_parser_unit(void) {
|
||||
scc_ast_decl_t int_decl = {
|
||||
.base.type = SCC_AST_DECL_VAR,
|
||||
.var.name = "a",
|
||||
.var.init = null,
|
||||
.var.type = &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT},
|
||||
};
|
||||
SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration);
|
||||
|
||||
scc_ast_decl_t func_decl = {
|
||||
.base.type = SCC_AST_DECL_FUNC,
|
||||
.func.name = "main",
|
||||
.func.body =
|
||||
&(scc_ast_stmt_t){
|
||||
.base.type = SCC_AST_STMT_COMPOUND,
|
||||
.compound.block_items = {0},
|
||||
},
|
||||
.func.type =
|
||||
&(scc_ast_type_t){
|
||||
.base.type = SCC_AST_TYPE_FUNCTION,
|
||||
.function.is_variadic = false,
|
||||
.function.param_types = {0},
|
||||
.function.return_type =
|
||||
&(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT},
|
||||
},
|
||||
};
|
||||
SCC_CHECK_AST(&func_decl.base, "int main(void) {}", scc_parse_declaration);
|
||||
|
||||
scc_ast_decl_t *decls[] = {&func_decl};
|
||||
scc_ast_translation_unit_t tu = {
|
||||
.base.type = SCC_AST_TRANSLATION_UNIT,
|
||||
.declarations.data = decls,
|
||||
.declarations.cap = 1,
|
||||
.declarations.size = 1,
|
||||
};
|
||||
SCC_CHECK_AST(&tu.base, "int main(void) {}", scc_parse_translation_unit);
|
||||
// SCC_CHECK_AST(&func_decl.base, "int main(void);", scc_parse_declaration);
|
||||
|
||||
// 1. 变量声明 int a;
|
||||
{
|
||||
scc_ast_node_t *items[] = {
|
||||
(scc_ast_node_t *)&(scc_ast_stmt_t){
|
||||
.base.type = SCC_AST_STMT_RETURN,
|
||||
.return_stmt.expr =
|
||||
&(scc_ast_expr_t){
|
||||
.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "65536",
|
||||
},
|
||||
},
|
||||
};
|
||||
scc_ast_decl_t func_decl = {
|
||||
.base.type = SCC_AST_DECL_FUNC,
|
||||
.func.name = "main",
|
||||
.func.body =
|
||||
&(scc_ast_stmt_t){
|
||||
.base.type = SCC_AST_STMT_COMPOUND,
|
||||
.compound.block_items.cap = 1,
|
||||
.compound.block_items.size = 1,
|
||||
.compound.block_items.data = items,
|
||||
},
|
||||
.func.type =
|
||||
&(scc_ast_type_t){
|
||||
.base.type = SCC_AST_TYPE_FUNCTION,
|
||||
.function.is_variadic = false,
|
||||
.function.param_types = {0},
|
||||
.function.return_type =
|
||||
&(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type =
|
||||
SCC_AST_BUILTIN_TYPE_INT},
|
||||
},
|
||||
};
|
||||
scc_ast_decl_t *decls[] = {&func_decl};
|
||||
scc_ast_translation_unit_t tu = {
|
||||
.base.type = SCC_AST_TRANSLATION_UNIT,
|
||||
.declarations.cap = 1,
|
||||
.declarations.size = 1,
|
||||
.declarations.data = decls,
|
||||
};
|
||||
scc_ast_decl_t int_decl;
|
||||
scc_ast_decl_val_init(
|
||||
&int_decl, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null);
|
||||
SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration);
|
||||
}
|
||||
|
||||
// 2. 函数声明 int main(void) {}
|
||||
{
|
||||
// 构造函数类型:返回 int,参数为空
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int,
|
||||
null); // 无参数,非可变参数
|
||||
|
||||
// 构造复合语句块(空)
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null);
|
||||
|
||||
// 构造函数声明
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
|
||||
|
||||
SCC_CHECK_AST(&func_decl.base, "int main(void) {}",
|
||||
scc_parse_declaration);
|
||||
}
|
||||
|
||||
// 3. 翻译单元包含一个函数定义
|
||||
{
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, null);
|
||||
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null);
|
||||
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
|
||||
|
||||
// 构造翻译单元
|
||||
scc_ast_decl_vec_t tu_decls;
|
||||
scc_vec_init(tu_decls);
|
||||
scc_vec_push(tu_decls, &func_decl);
|
||||
|
||||
scc_ast_translation_unit_t tu;
|
||||
scc_ast_translation_unit_init(&tu, &tu_decls);
|
||||
|
||||
SCC_CHECK_AST(&tu.base, "int main(void) {}",
|
||||
scc_parse_translation_unit);
|
||||
}
|
||||
|
||||
// 4. 带返回语句的函数 int main(void) { return 65536; }
|
||||
{
|
||||
// 返回语句中的整数常量
|
||||
scc_ast_expr_t ret_val;
|
||||
scc_ast_expr_literal_int_init(&ret_val, "65536", false);
|
||||
|
||||
scc_ast_stmt_t ret_stmt;
|
||||
scc_ast_stmt_return_init(&ret_stmt, &ret_val);
|
||||
|
||||
// 复合语句包含该返回语句
|
||||
scc_ast_block_item_vec_t items;
|
||||
scc_vec_init(items);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&ret_stmt);
|
||||
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, &items); // items 被移动
|
||||
|
||||
// 函数类型
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, null);
|
||||
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
|
||||
|
||||
scc_ast_decl_vec_t tu_decls;
|
||||
scc_vec_init(tu_decls);
|
||||
scc_vec_push(tu_decls, &func_decl);
|
||||
|
||||
scc_ast_translation_unit_t tu;
|
||||
scc_ast_translation_unit_init(&tu, &tu_decls);
|
||||
|
||||
SCC_CHECK_AST(&tu.base, "int main(void) { return 65536; }",
|
||||
scc_parse_translation_unit);
|
||||
}
|
||||
|
||||
// 5. 多语句函数(复杂示例)
|
||||
{
|
||||
// 修复后的测试用例:正确表示多语句函数
|
||||
// 创建变量声明: int a;
|
||||
scc_ast_type_t a_type = {.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT};
|
||||
scc_ast_decl_t a_decl = {.base.type = SCC_AST_DECL_VAR,
|
||||
.var.name = "a",
|
||||
.var.type = &a_type};
|
||||
// 变量声明 int a;
|
||||
scc_ast_decl_t a_decl;
|
||||
scc_ast_decl_val_init(&a_decl, &scc_ast_builtin_type_int, "a", null);
|
||||
|
||||
// 创建变量声明: int b;
|
||||
scc_ast_type_t b_type = {.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT};
|
||||
scc_ast_decl_t b_decl = {.base.type = SCC_AST_DECL_VAR,
|
||||
.var.name = "b",
|
||||
.var.type = &b_type};
|
||||
// 变量声明 int b;
|
||||
scc_ast_decl_t b_decl;
|
||||
scc_ast_decl_val_init(&b_decl, &scc_ast_builtin_type_int, "b", null);
|
||||
|
||||
// 创建表达式: 1 + 2 * 3
|
||||
scc_ast_expr_t expr1_3 = {.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "3"};
|
||||
scc_ast_expr_t expr1_2 = {.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "2"};
|
||||
scc_ast_expr_t expr1_mul = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_MUL,
|
||||
.binary.lhs = &expr1_2,
|
||||
.binary.rhs = &expr1_3};
|
||||
scc_ast_expr_t expr1_1 = {.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "1"};
|
||||
scc_ast_expr_t expr1_add = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_ADD,
|
||||
.binary.lhs = &expr1_1,
|
||||
.binary.rhs = &expr1_mul};
|
||||
// 表达式 1 + 2 * 3
|
||||
scc_ast_expr_t lit1, lit2, lit3, mul, add;
|
||||
scc_ast_expr_literal_int_init(&lit1, "1", false);
|
||||
scc_ast_expr_literal_int_init(&lit2, "2", false);
|
||||
scc_ast_expr_literal_int_init(&lit3, "3", false);
|
||||
scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3);
|
||||
scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &mul);
|
||||
|
||||
// 创建赋值语句: a = 1 + 2 * 3;
|
||||
scc_ast_expr_t a_expr1 = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "a"};
|
||||
scc_ast_expr_t assign1 = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_ASSIGN,
|
||||
.binary.lhs = &a_expr1,
|
||||
.binary.rhs = &expr1_add};
|
||||
scc_ast_stmt_t assign1_stmt = {.base.type = SCC_AST_STMT_EXPR,
|
||||
.expr.expr = &assign1};
|
||||
// 赋值 a = 1 + 2 * 3;
|
||||
scc_ast_expr_t a_ref1, assign1;
|
||||
scc_ast_expr_identifier_init(&a_ref1, "a");
|
||||
scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add);
|
||||
scc_ast_stmt_t assign1_stmt;
|
||||
scc_ast_stmt_expr_init(&assign1_stmt, &assign1);
|
||||
|
||||
// 创建赋值语句: b = 7;
|
||||
scc_ast_expr_t expr2_7 = {.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "7"};
|
||||
scc_ast_expr_t b_expr1 = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "b"};
|
||||
scc_ast_expr_t assign2 = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_ASSIGN,
|
||||
.binary.lhs = &b_expr1,
|
||||
.binary.rhs = &expr2_7};
|
||||
scc_ast_stmt_t assign2_stmt = {.base.type = SCC_AST_STMT_EXPR,
|
||||
.expr.expr = &assign2};
|
||||
// 赋值 b = 7;
|
||||
scc_ast_expr_t lit7;
|
||||
scc_ast_expr_literal_int_init(&lit7, "7", false);
|
||||
scc_ast_expr_t b_ref1, assign2;
|
||||
scc_ast_expr_identifier_init(&b_ref1, "b");
|
||||
scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7);
|
||||
scc_ast_stmt_t assign2_stmt;
|
||||
scc_ast_stmt_expr_init(&assign2_stmt, &assign2);
|
||||
|
||||
// 创建表达式: a - b + 1
|
||||
scc_ast_expr_t a_expr2 = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "a"};
|
||||
scc_ast_expr_t b_expr2 = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "b"};
|
||||
scc_ast_expr_t sub_expr = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_SUB,
|
||||
.binary.lhs = &a_expr2,
|
||||
.binary.rhs = &b_expr2};
|
||||
scc_ast_expr_t expr3_1 = {.base.type = SCC_AST_EXPR_INT_LITERAL,
|
||||
.literal.lexme = "1"};
|
||||
scc_ast_expr_t add_expr = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_ADD,
|
||||
.binary.lhs = &sub_expr,
|
||||
.binary.rhs = &expr3_1};
|
||||
// 表达式 a - b + 1
|
||||
scc_ast_expr_t a_ref2, b_ref2, sub, add2, lit1_2;
|
||||
scc_ast_expr_identifier_init(&a_ref2, "a");
|
||||
scc_ast_expr_identifier_init(&b_ref2, "b");
|
||||
scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2);
|
||||
scc_ast_expr_literal_int_init(&lit1_2, "1", false);
|
||||
scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2);
|
||||
|
||||
// 创建赋值语句: a = a - b + 1;
|
||||
scc_ast_expr_t a_expr3 = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "a"};
|
||||
scc_ast_expr_t assign3 = {.base.type = SCC_AST_EXPR_BINARY,
|
||||
.binary.op = SCC_AST_OP_ASSIGN,
|
||||
.binary.lhs = &a_expr3,
|
||||
.binary.rhs = &add_expr};
|
||||
scc_ast_stmt_t assign3_stmt = {.base.type = SCC_AST_STMT_EXPR,
|
||||
.expr.expr = &assign3};
|
||||
// 赋值 a = a - b + 1;
|
||||
scc_ast_expr_t a_ref3, assign3;
|
||||
scc_ast_expr_identifier_init(&a_ref3, "a");
|
||||
scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2);
|
||||
scc_ast_stmt_t assign3_stmt;
|
||||
scc_ast_stmt_expr_init(&assign3_stmt, &assign3);
|
||||
|
||||
// 创建return语句: return a;
|
||||
scc_ast_expr_t return_expr = {.base.type = SCC_AST_EXPR_IDENTIFIER,
|
||||
.identifier.name = "a"};
|
||||
scc_ast_stmt_t return_stmt = {.base.type = SCC_AST_STMT_RETURN,
|
||||
.return_stmt.expr = &return_expr};
|
||||
// return a;
|
||||
scc_ast_expr_t a_ref4;
|
||||
scc_ast_expr_identifier_init(&a_ref4, "a");
|
||||
scc_ast_stmt_t ret_stmt;
|
||||
scc_ast_stmt_return_init(&ret_stmt, &a_ref4);
|
||||
|
||||
// 创建复合语句块
|
||||
scc_ast_node_t *items[] = {
|
||||
(scc_ast_node_t *)&a_decl, (scc_ast_node_t *)&b_decl,
|
||||
(scc_ast_node_t *)&assign1_stmt, (scc_ast_node_t *)&assign2_stmt,
|
||||
(scc_ast_node_t *)&assign3_stmt, (scc_ast_node_t *)&return_stmt};
|
||||
// 复合语句块,按顺序放入
|
||||
scc_ast_block_item_vec_t items;
|
||||
scc_vec_init(items);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&a_decl);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&b_decl);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&assign1_stmt);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&assign2_stmt);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&assign3_stmt);
|
||||
scc_vec_push(items, (scc_ast_node_t *)&ret_stmt);
|
||||
|
||||
scc_ast_type_t return_type = {.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT};
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, &items);
|
||||
|
||||
scc_ast_type_t func_type = {.base.type = SCC_AST_TYPE_FUNCTION,
|
||||
.function.is_variadic = false,
|
||||
.function.param_types = {0},
|
||||
.function.return_type = &return_type};
|
||||
// 函数类型
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(
|
||||
&func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
|
||||
|
||||
scc_ast_decl_t func_decl = {
|
||||
.base.type = SCC_AST_DECL_FUNC,
|
||||
.func.name = "main",
|
||||
.func.body = &(scc_ast_stmt_t){.base.type = SCC_AST_STMT_COMPOUND,
|
||||
.compound.block_items.cap = 6,
|
||||
.compound.block_items.size = 6,
|
||||
.compound.block_items.data = items},
|
||||
.func.type = &func_type};
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
|
||||
|
||||
scc_ast_decl_t *decls[] = {&func_decl};
|
||||
scc_ast_translation_unit_t tu = {.base.type = SCC_AST_TRANSLATION_UNIT,
|
||||
.declarations.cap = 1,
|
||||
.declarations.size = 1,
|
||||
.declarations.data = decls};
|
||||
scc_ast_decl_vec_t tu_decls;
|
||||
scc_vec_init(tu_decls);
|
||||
scc_vec_push(tu_decls, &func_decl);
|
||||
|
||||
SCC_CHECK_AST(&tu.base,
|
||||
"int main() {\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" a = 1 + 2 * 3;\n"
|
||||
" b = 7;\n"
|
||||
" a = a - b + 1;\n"
|
||||
" return a;\n"
|
||||
"}\n",
|
||||
scc_parse_translation_unit);
|
||||
scc_ast_translation_unit_t tu;
|
||||
scc_ast_translation_unit_init(&tu, &tu_decls);
|
||||
|
||||
const char *input = "int main() {\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" a = 1 + 2 * 3;\n"
|
||||
" b = 7;\n"
|
||||
" a = a - b + 1;\n"
|
||||
" return a;\n"
|
||||
"}\n";
|
||||
|
||||
SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit);
|
||||
}
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_binary(scc_ast_expr_op_t op, scc_ast_expr_t *lhs,
|
||||
scc_ast_expr_t *rhs) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_BINARY};
|
||||
expr.binary.op = op;
|
||||
expr.binary.lhs = lhs;
|
||||
expr.binary.rhs = rhs;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_unary(scc_ast_expr_op_t op,
|
||||
scc_ast_expr_t *operand) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_UNARY};
|
||||
expr.unary.op = op;
|
||||
expr.unary.operand = operand;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_identifier(char *name) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_IDENTIFIER};
|
||||
expr.identifier.name = name;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_int_literal(char *val) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_INT_LITERAL};
|
||||
expr.literal.lexme = val;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_float_literal(char *val) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_FLOAT_LITERAL};
|
||||
expr.literal.lexme = val;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_string_literal(char *val) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_STRING_LITERAL};
|
||||
expr.literal.lexme = val;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_char_literal(char *val) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_CHAR_LITERAL};
|
||||
expr.literal.lexme = val;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_conditional(scc_ast_expr_t *cond,
|
||||
scc_ast_expr_t *then_expr,
|
||||
scc_ast_expr_t *else_expr) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_COND};
|
||||
expr.cond.cond = cond;
|
||||
expr.cond.then_expr = then_expr;
|
||||
expr.cond.else_expr = else_expr;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static scc_ast_expr_t make_call(scc_ast_expr_t *callee,
|
||||
scc_ast_expr_vec_t *args) {
|
||||
scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_CALL};
|
||||
expr.call.callee = callee;
|
||||
// 注意:args 需要提前初始化,此处简化处理,实际测试中可能需要动态分配
|
||||
// 我们将在具体测试中手动初始化 args 数组
|
||||
return expr;
|
||||
}
|
||||
|
||||
static void test_parser_expression(void) {
|
||||
// 1. 基本表达式:标识符、整数常量、字符串字面量、括号
|
||||
// 1. 基本表达式
|
||||
{
|
||||
scc_ast_expr_t ident = make_identifier("x");
|
||||
scc_ast_expr_t ident;
|
||||
scc_ast_expr_identifier_init(&ident, "x");
|
||||
SCC_CHECK_AST(&ident.base, "x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t int_lit = make_int_literal("42");
|
||||
scc_ast_expr_t int_lit;
|
||||
scc_ast_expr_literal_int_init(&int_lit, "42", false);
|
||||
SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t str_lit = make_string_literal("\"hello\"");
|
||||
scc_ast_expr_t str_lit;
|
||||
scc_ast_expr_literal_string_init(&str_lit, "\"hello\"", false);
|
||||
SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression);
|
||||
|
||||
// 括号表达式
|
||||
scc_ast_expr_t paren_ident = make_identifier("y");
|
||||
// 括号表达式(解析器应直接返回内部表达式)
|
||||
scc_ast_expr_t paren_ident;
|
||||
scc_ast_expr_identifier_init(&paren_ident, "y");
|
||||
SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 2. 后缀表达式
|
||||
{
|
||||
// 数组下标:a[10]
|
||||
scc_ast_expr_t a = make_identifier("a");
|
||||
scc_ast_expr_t index = make_int_literal("10");
|
||||
scc_ast_expr_t subscript = {.base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT};
|
||||
subscript.subscript.array = &a;
|
||||
subscript.subscript.index = &index;
|
||||
// 数组下标 a[10]
|
||||
scc_ast_expr_t a, index, subscript;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_literal_int_init(&index, "10", false);
|
||||
scc_ast_expr_array_subscript_init(&subscript, &a, &index);
|
||||
SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression);
|
||||
|
||||
// 函数调用:f()
|
||||
scc_ast_expr_t f = make_identifier("f");
|
||||
scc_ast_expr_t call = {.base.type = SCC_AST_EXPR_CALL};
|
||||
call.call.callee = &f;
|
||||
// 函数调用 f()
|
||||
scc_ast_expr_t f;
|
||||
scc_ast_expr_identifier_init(&f, "f");
|
||||
scc_ast_expr_vec_t args;
|
||||
scc_vec_init(args);
|
||||
call.call.args = args; // 空参数列表
|
||||
scc_ast_expr_t call;
|
||||
scc_ast_expr_call_init(&call, "f",
|
||||
&args); // 使用函数名,target 在语义分析时填充
|
||||
SCC_CHECK_AST(&call.base, "f()", scc_parse_expression);
|
||||
|
||||
// 函数调用带参数:f(1, x)
|
||||
scc_ast_expr_t f2 = make_identifier("f");
|
||||
scc_ast_expr_t arg1 = make_int_literal("1");
|
||||
scc_ast_expr_t arg2 = make_identifier("x");
|
||||
// 函数调用带参数 f(1, x)
|
||||
scc_ast_expr_t arg1, arg2;
|
||||
scc_ast_expr_literal_int_init(&arg1, "1", false);
|
||||
scc_ast_expr_identifier_init(&arg2, "x");
|
||||
scc_ast_expr_vec_t args2;
|
||||
scc_vec_init(args2);
|
||||
scc_vec_push(args2, &arg1);
|
||||
scc_vec_push(args2, &arg2);
|
||||
scc_ast_expr_t call2 = {.base.type = SCC_AST_EXPR_CALL};
|
||||
call2.call.callee = &f2;
|
||||
call2.call.args = args2;
|
||||
scc_ast_expr_t call2;
|
||||
scc_ast_expr_call_init(&call2, "f", &args2);
|
||||
SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression);
|
||||
|
||||
// 成员访问 . 和 ->
|
||||
scc_ast_expr_t s = make_identifier("s");
|
||||
scc_ast_expr_t dot = {.base.type = SCC_AST_EXPR_MEMBER};
|
||||
dot.member.base = &s;
|
||||
dot.member.member_name = "field";
|
||||
// 成员访问 .
|
||||
scc_ast_expr_t s, dot;
|
||||
scc_ast_expr_identifier_init(&s, "s");
|
||||
scc_ast_expr_member_init(&dot, &s, "field");
|
||||
SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t p = make_identifier("p");
|
||||
scc_ast_expr_t arrow = {.base.type = SCC_AST_EXPR_PTR_MEMBER};
|
||||
arrow.ptr_member.base = &p;
|
||||
arrow.ptr_member.member_name = "field";
|
||||
// 指针成员访问 ->
|
||||
scc_ast_expr_t p, arrow;
|
||||
scc_ast_expr_identifier_init(&p, "p");
|
||||
scc_ast_expr_ptr_member_init(&arrow, &p, "field");
|
||||
SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression);
|
||||
|
||||
// 后缀 ++/--
|
||||
scc_ast_expr_t x = make_identifier("x");
|
||||
scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &x);
|
||||
scc_ast_expr_t x, post_inc, post_dec;
|
||||
scc_ast_expr_identifier_init(&x, "x");
|
||||
scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &x);
|
||||
scc_ast_expr_unary_init(&post_dec, SCC_AST_OP_POSTFIX_DECREMENT, &x);
|
||||
SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t post_dec = make_unary(SCC_AST_OP_POSTFIX_DECREMENT, &x);
|
||||
SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression);
|
||||
|
||||
// 复合字面量 TODO: (int){1,2} 需要更复杂的构造,暂略
|
||||
// SCC_CHECK_AST(..., "(int){1,2}", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 3. 一元表达式
|
||||
{
|
||||
scc_ast_expr_t x = make_identifier("x");
|
||||
scc_ast_expr_t x;
|
||||
scc_ast_expr_identifier_init(&x, "x");
|
||||
|
||||
scc_ast_expr_t pre_inc = make_unary(SCC_AST_OP_PREFIX_INCREMENT, &x);
|
||||
scc_ast_expr_t pre_inc;
|
||||
scc_ast_expr_unary_init(&pre_inc, SCC_AST_OP_PREFIX_INCREMENT, &x);
|
||||
SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t pre_dec = make_unary(SCC_AST_OP_PREFIX_DECREMENT, &x);
|
||||
scc_ast_expr_t pre_dec;
|
||||
scc_ast_expr_unary_init(&pre_dec, SCC_AST_OP_PREFIX_DECREMENT, &x);
|
||||
SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t addr = make_unary(SCC_AST_OP_ADDRESS_OF, &x);
|
||||
scc_ast_expr_t addr;
|
||||
scc_ast_expr_unary_init(&addr, SCC_AST_OP_ADDRESS_OF, &x);
|
||||
SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t deref = make_unary(SCC_AST_OP_INDIRECTION, &x);
|
||||
scc_ast_expr_t deref;
|
||||
scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &x);
|
||||
SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t plus = make_unary(SCC_AST_OP_UNARY_PLUS, &x);
|
||||
scc_ast_expr_t plus;
|
||||
scc_ast_expr_unary_init(&plus, SCC_AST_OP_UNARY_PLUS, &x);
|
||||
SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t minus = make_unary(SCC_AST_OP_UNARY_MINUS, &x);
|
||||
scc_ast_expr_t minus;
|
||||
scc_ast_expr_unary_init(&minus, SCC_AST_OP_UNARY_MINUS, &x);
|
||||
SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t bit_not = make_unary(SCC_AST_OP_BITWISE_NOT, &x);
|
||||
scc_ast_expr_t bit_not;
|
||||
scc_ast_expr_unary_init(&bit_not, SCC_AST_OP_BITWISE_NOT, &x);
|
||||
SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t log_not = make_unary(SCC_AST_OP_LOGICAL_NOT, &x);
|
||||
scc_ast_expr_t log_not;
|
||||
scc_ast_expr_unary_init(&log_not, SCC_AST_OP_LOGICAL_NOT, &x);
|
||||
SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression);
|
||||
|
||||
// sizeof 两种形式
|
||||
// sizeof 表达式
|
||||
scc_ast_expr_t sizeof_expr = {.base.type = SCC_AST_EXPR_SIZE_OF};
|
||||
sizeof_expr.attr_of.expr = &x;
|
||||
SCC_CHECK_AST(&sizeof_expr.base, "sizeof x", scc_parse_expression);
|
||||
|
||||
// sizeof(类型名) 需要构造类型节点,暂时略,用TODO
|
||||
// SCC_CHECK_AST(..., "sizeof(int)", scc_parse_expression);
|
||||
// TODO
|
||||
// scc_ast_expr_t sizeof_expr;
|
||||
// scc_ast_expr_sizeof_expr_init(&sizeof_expr, &x);
|
||||
// SCC_CHECK_AST(&sizeof_expr.base, "sizeof x", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 4. 类型转换
|
||||
// 4. 类型转换(示例: (int)x )
|
||||
{
|
||||
// (int)x
|
||||
// 需要构造类型节点,这里简化,用TODO
|
||||
// scc_ast_type_t int_type = { .base.type = SCC_AST_TYPE_BUILTIN,
|
||||
// .builtin.type = SCC_AST_BUILTIN_TYPE_INT }; scc_ast_expr_t x =
|
||||
// make_identifier("x"); scc_ast_expr_t cast = { .base.type =
|
||||
// SCC_AST_EXPR_CAST }; cast.cast.type = &int_type; cast.cast.expr =
|
||||
// &x; SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression);
|
||||
// scc_ast_type_t
|
||||
// int_type; // 使用内置类型全局变量即可,但类型转换需要一个类型节点
|
||||
// //
|
||||
// 我们可以直接使用全局内置类型的地址,但类型转换节点需要一个类型节点,直接引用全局即可
|
||||
// // TODO
|
||||
// scc_ast_expr_t x;
|
||||
// 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. 二元运算符优先级
|
||||
{
|
||||
scc_ast_expr_t a = make_identifier("a");
|
||||
scc_ast_expr_t b = make_identifier("b");
|
||||
scc_ast_expr_t c = make_identifier("c");
|
||||
scc_ast_expr_t d = make_identifier("d");
|
||||
scc_ast_expr_t a, b, c, d;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_identifier_init(&b, "b");
|
||||
scc_ast_expr_identifier_init(&c, "c");
|
||||
scc_ast_expr_identifier_init(&d, "d");
|
||||
|
||||
// 乘除模优先级高于加减
|
||||
scc_ast_expr_t mul = make_binary(SCC_AST_OP_MUL, &a, &b);
|
||||
scc_ast_expr_t add = make_binary(SCC_AST_OP_ADD, &mul, &c);
|
||||
// a * b + c
|
||||
scc_ast_expr_t mul, add;
|
||||
scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &a, &b);
|
||||
scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &mul, &c);
|
||||
SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression);
|
||||
|
||||
// 左结合性 a - b - c => (a - b) - c
|
||||
scc_ast_expr_t sub1 = make_binary(SCC_AST_OP_SUB, &a, &b);
|
||||
scc_ast_expr_t sub2 = make_binary(SCC_AST_OP_SUB, &sub1, &c);
|
||||
// a - b - c => (a - b) - c
|
||||
scc_ast_expr_t sub1, sub2;
|
||||
scc_ast_expr_binary_init(&sub1, SCC_AST_OP_SUB, &a, &b);
|
||||
scc_ast_expr_binary_init(&sub2, SCC_AST_OP_SUB, &sub1, &c);
|
||||
SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression);
|
||||
|
||||
// 移位
|
||||
scc_ast_expr_t shift = make_binary(SCC_AST_OP_LEFT_SHIFT, &a, &b);
|
||||
// a << b
|
||||
scc_ast_expr_t shift;
|
||||
scc_ast_expr_binary_init(&shift, SCC_AST_OP_LEFT_SHIFT, &a, &b);
|
||||
SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression);
|
||||
|
||||
// 关系
|
||||
scc_ast_expr_t lt = make_binary(SCC_AST_OP_LESS, &a, &b);
|
||||
// a < b
|
||||
scc_ast_expr_t lt;
|
||||
scc_ast_expr_binary_init(<, SCC_AST_OP_LESS, &a, &b);
|
||||
SCC_CHECK_AST(<.base, "a < b", scc_parse_expression);
|
||||
|
||||
// 相等
|
||||
scc_ast_expr_t eq = make_binary(SCC_AST_OP_EQUAL, &a, &b);
|
||||
// a == b
|
||||
scc_ast_expr_t eq;
|
||||
scc_ast_expr_binary_init(&eq, SCC_AST_OP_EQUAL, &a, &b);
|
||||
SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression);
|
||||
|
||||
// 按位与、异或、或的优先级:& 高于 ^ 高于 |
|
||||
scc_ast_expr_t bitand = make_binary(SCC_AST_OP_BITWISE_AND, &a, &b);
|
||||
scc_ast_expr_t bitxor =
|
||||
make_binary(SCC_AST_OP_BITWISE_XOR, &bitand, &c);
|
||||
scc_ast_expr_t bitor = make_binary(SCC_AST_OP_BITWISE_OR, &bitxor, &d);
|
||||
// a & b ^ c | d
|
||||
scc_ast_expr_t bitand, bitxor, bitor;
|
||||
scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b);
|
||||
scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c);
|
||||
scc_ast_expr_binary_init(&bitor, SCC_AST_OP_BITWISE_OR, &bitxor, &d);
|
||||
SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression);
|
||||
|
||||
// 逻辑与、或:&& 高于 ||
|
||||
scc_ast_expr_t logand = make_binary(SCC_AST_OP_LOGICAL_AND, &a, &b);
|
||||
scc_ast_expr_t logor = make_binary(SCC_AST_OP_LOGICAL_OR, &logand, &c);
|
||||
// a && b || c
|
||||
scc_ast_expr_t logand, logor;
|
||||
scc_ast_expr_binary_init(&logand, SCC_AST_OP_LOGICAL_AND, &a, &b);
|
||||
scc_ast_expr_binary_init(&logor, SCC_AST_OP_LOGICAL_OR, &logand, &c);
|
||||
SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 6. 三元运算符
|
||||
{
|
||||
scc_ast_expr_t cond = make_identifier("a");
|
||||
scc_ast_expr_t then_expr = make_identifier("b");
|
||||
scc_ast_expr_t else_expr = make_identifier("c");
|
||||
scc_ast_expr_t cond_expr =
|
||||
make_conditional(&cond, &then_expr, &else_expr);
|
||||
SCC_CHECK_AST(&cond_expr.base, "a ? b : c", scc_parse_expression);
|
||||
scc_ast_expr_t a, b, c;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_identifier_init(&b, "b");
|
||||
scc_ast_expr_identifier_init(&c, "c");
|
||||
|
||||
// 右结合性 a ? b : c ? d : e => a ? b : (c ? d : e)
|
||||
scc_ast_expr_t cond2 = make_identifier("c");
|
||||
scc_ast_expr_t then2 = make_identifier("d");
|
||||
scc_ast_expr_t else2 = make_identifier("e");
|
||||
scc_ast_expr_t inner_cond = make_conditional(&cond2, &then2, &else2);
|
||||
scc_ast_expr_t outer_cond =
|
||||
make_conditional(&cond, &then_expr, &inner_cond);
|
||||
SCC_CHECK_AST(&outer_cond.base, "a ? b : c ? d : e",
|
||||
scc_parse_expression);
|
||||
// a ? b : c
|
||||
scc_ast_expr_t cond1;
|
||||
scc_ast_expr_cond_init(&cond1, &a, &b, &c);
|
||||
SCC_CHECK_AST(&cond1.base, "a ? b : c", scc_parse_expression);
|
||||
|
||||
// a ? b : c ? d : e => a ? b : (c ? d : e)
|
||||
scc_ast_expr_t d, e;
|
||||
scc_ast_expr_identifier_init(&d, "d");
|
||||
scc_ast_expr_identifier_init(&e, "e");
|
||||
scc_ast_expr_t inner, outer;
|
||||
scc_ast_expr_cond_init(&inner, &c, &d, &e);
|
||||
scc_ast_expr_cond_init(&outer, &a, &b, &inner);
|
||||
SCC_CHECK_AST(&outer.base, "a ? b : c ? d : e", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 7. 赋值运算符(右结合)
|
||||
// 7. 赋值运算符
|
||||
{
|
||||
scc_ast_expr_t a = make_identifier("a");
|
||||
scc_ast_expr_t b = make_identifier("b");
|
||||
scc_ast_expr_t c = make_identifier("c");
|
||||
scc_ast_expr_t int_lit = make_int_literal("42");
|
||||
scc_ast_expr_t assign1 = make_binary(SCC_AST_OP_ASSIGN, &b, &c);
|
||||
scc_ast_expr_t assign2 =
|
||||
make_binary(SCC_AST_OP_ASSIGN, &a, &assign1); // a = (b = c)
|
||||
SCC_CHECK_AST(&assign2.base, "a = b = c", scc_parse_expression);
|
||||
scc_ast_expr_t a, b, c;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_identifier_init(&b, "b");
|
||||
scc_ast_expr_identifier_init(&c, "c");
|
||||
scc_ast_expr_t lit42;
|
||||
scc_ast_expr_literal_int_init(&lit42, "42", false);
|
||||
|
||||
scc_ast_expr_t assign3 = make_binary(SCC_AST_OP_ASSIGN, &a, &int_lit);
|
||||
SCC_CHECK_AST(&assign3.base, "a = 42", scc_parse_expression);
|
||||
// a = b = c
|
||||
scc_ast_expr_t assign_inner, assign_outer;
|
||||
scc_ast_expr_binary_init(&assign_inner, SCC_AST_OP_ASSIGN, &b, &c);
|
||||
scc_ast_expr_binary_init(&assign_outer, SCC_AST_OP_ASSIGN, &a,
|
||||
&assign_inner);
|
||||
SCC_CHECK_AST(&assign_outer.base, "a = b = c", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t assign4 = make_binary(SCC_AST_OP_SUB, &a, &b);
|
||||
scc_ast_expr_t assign5 =
|
||||
make_binary(SCC_AST_OP_ADD, &assign4, &int_lit);
|
||||
scc_ast_expr_t assign6 = make_binary(SCC_AST_OP_ASSIGN, &a, &assign5);
|
||||
SCC_CHECK_AST(&assign6.base, "a = a - b + 42", scc_parse_expression);
|
||||
// a = 42
|
||||
scc_ast_expr_t assign1;
|
||||
scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a, &lit42);
|
||||
SCC_CHECK_AST(&assign1.base, "a = 42", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t add_assign = make_binary(SCC_AST_OP_ASSIGN_ADD, &a, &b);
|
||||
// a = a - b + 42
|
||||
scc_ast_expr_t sub, add, assign2;
|
||||
scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a, &b);
|
||||
scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &sub, &lit42);
|
||||
scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &a, &add);
|
||||
SCC_CHECK_AST(&assign2.base, "a = a - b + 42", scc_parse_expression);
|
||||
|
||||
// a += b
|
||||
scc_ast_expr_t add_assign;
|
||||
scc_ast_expr_binary_init(&add_assign, SCC_AST_OP_ASSIGN_ADD, &a, &b);
|
||||
SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 8. 逗号运算符
|
||||
{
|
||||
scc_ast_expr_t a = make_identifier("a");
|
||||
scc_ast_expr_t b = make_identifier("b");
|
||||
scc_ast_expr_t comma1 = make_binary(SCC_AST_OP_COMMA, &a, &b);
|
||||
SCC_CHECK_AST(&comma1.base, "a, b", scc_parse_expression);
|
||||
scc_ast_expr_t a, b;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_identifier_init(&b, "b");
|
||||
scc_ast_expr_t comma;
|
||||
scc_ast_expr_binary_init(&comma, SCC_AST_OP_COMMA, &a, &b);
|
||||
SCC_CHECK_AST(&comma.base, "a, b", scc_parse_expression);
|
||||
}
|
||||
|
||||
// 9. 混合优先级测试
|
||||
// 9. 混合优先级
|
||||
{
|
||||
scc_ast_expr_t a = make_identifier("a");
|
||||
scc_ast_expr_t b = make_identifier("b");
|
||||
scc_ast_expr_t c = make_identifier("c");
|
||||
scc_ast_expr_t d = make_identifier("d");
|
||||
scc_ast_expr_t a, b, c, d;
|
||||
scc_ast_expr_identifier_init(&a, "a");
|
||||
scc_ast_expr_identifier_init(&b, "b");
|
||||
scc_ast_expr_identifier_init(&c, "c");
|
||||
scc_ast_expr_identifier_init(&d, "d");
|
||||
|
||||
// a + b * c - d => (a + (b * c)) - d
|
||||
scc_ast_expr_t mul = make_binary(SCC_AST_OP_MUL, &b, &c);
|
||||
scc_ast_expr_t add = make_binary(SCC_AST_OP_ADD, &a, &mul);
|
||||
scc_ast_expr_t sub = make_binary(SCC_AST_OP_SUB, &add, &d);
|
||||
// a + b * c - d
|
||||
scc_ast_expr_t mul, add, sub;
|
||||
scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c);
|
||||
scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &a, &mul);
|
||||
scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &add, &d);
|
||||
SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression);
|
||||
|
||||
// *p++ => *(p++)
|
||||
scc_ast_expr_t p = make_identifier("p");
|
||||
scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &p);
|
||||
scc_ast_expr_t deref = make_unary(SCC_AST_OP_INDIRECTION, &post_inc);
|
||||
// *p++
|
||||
scc_ast_expr_t p, post_inc, deref;
|
||||
scc_ast_expr_identifier_init(&p, "p");
|
||||
scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &p);
|
||||
scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &post_inc);
|
||||
SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression);
|
||||
}
|
||||
}
|
||||
@@ -586,5 +525,5 @@ static void test_parser_expression(void) {
|
||||
TEST_LIST = {
|
||||
{"parser_unit", test_parser_unit},
|
||||
{"parser_expression", test_parser_expression},
|
||||
{NULL, NULL},
|
||||
{null, null},
|
||||
};
|
||||
Reference in New Issue
Block a user