feat(ast): 添加内置类型定义和AST节点初始化函数

添加了完整的内置类型支持,包括整数、浮点数、字符、布尔等基本类型,
以及它们的有符号/无符号变体。同时添加了大量的AST节点初始化函数,
简化了AST节点的创建过程。

BREAKING CHANGE: 重构了AST表达式和声明结构,移除了冗余字段,
统一了命名规范,并修改了函数调用和成员访问的表示方式。
This commit is contained in:
zzy
2026-03-10 13:56:32 +08:00
parent 80714fe7e5
commit 2e331ee016
17 changed files with 981 additions and 581 deletions

View File

@@ -0,0 +1,30 @@
#ifndef __SCC_AST_BUILTIN_H__
#define __SCC_AST_BUILTIN_H__
#include "ast_def.h"
extern scc_ast_type_t scc_ast_builtin_type_int;
extern scc_ast_type_t scc_ast_builtin_type_float;
extern scc_ast_type_t scc_ast_builtin_type_double;
extern scc_ast_type_t scc_ast_builtin_type_char;
extern scc_ast_type_t scc_ast_builtin_type_void;
extern scc_ast_type_t scc_ast_builtin_type_long;
extern scc_ast_type_t scc_ast_builtin_type_long_long;
extern scc_ast_type_t scc_ast_builtin_type_short;
extern scc_ast_type_t scc_ast_builtin_type_bool;
extern scc_ast_type_t scc_ast_builtin_type_long_double;
extern scc_ast_type_t scc_ast_builtin_type_complex_float;
extern scc_ast_type_t scc_ast_builtin_type_complex_double;
extern scc_ast_type_t scc_ast_builtin_type_complex_long_double;
extern scc_ast_type_t scc_ast_builtin_type_unsigned_int;
extern scc_ast_type_t scc_ast_builtin_type_unsigned_long;
extern scc_ast_type_t scc_ast_builtin_type_unsigned_long_long;
extern scc_ast_type_t scc_ast_builtin_type_unsigned_short;
extern scc_ast_type_t scc_ast_builtin_type_unsigned_char;
extern scc_ast_type_t scc_ast_builtin_type_signed_int;
extern scc_ast_type_t scc_ast_builtin_type_signed_long;
extern scc_ast_type_t scc_ast_builtin_type_signed_long_long;
extern scc_ast_type_t scc_ast_builtin_type_signed_short;
extern scc_ast_type_t scc_ast_builtin_type_signed_char;
#endif

View File

@@ -108,6 +108,7 @@ typedef enum {
SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT, SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT,
SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE, SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE,
SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE, SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE,
SCC_AST_BUILTIN_TYPE_VA_LIST,
} scc_ast_builtin_type_t; } scc_ast_builtin_type_t;
/** /**
@@ -148,14 +149,13 @@ typedef SCC_VEC(scc_ast_node_t *) scc_ast_block_item_vec_t;
*/ */
struct scc_ast_type { struct scc_ast_type {
scc_ast_node_t base; scc_ast_node_t base;
scc_ast_decl_specifier_t quals;
union { union {
struct { struct {
scc_ast_builtin_type_t type; scc_ast_builtin_type_t type;
scc_ast_decl_specifier_t quals;
} builtin; } builtin;
struct { struct {
scc_ast_type_t *pointee; scc_ast_type_t *pointee;
scc_ast_decl_specifier_t quals;
} pointer; } pointer;
struct { struct {
scc_ast_type_t *element; scc_ast_type_t *element;
@@ -163,8 +163,7 @@ struct scc_ast_type {
} array; } array;
struct { struct {
scc_ast_type_t *return_type; scc_ast_type_t *return_type;
scc_ast_type_vec_t param_types; scc_ast_decl_vec_t param_types; // va_list <=> ...
cbool is_variadic; // va_arg <=> ...
} function; } function;
struct { struct {
const char *name; const char *name;
@@ -269,7 +268,8 @@ struct scc_ast_expr {
} cond; } cond;
// 函数调用 // 函数调用
struct { struct {
scc_ast_expr_t *callee; const char *name;
scc_ast_expr_t *_target;
scc_ast_expr_vec_t args; scc_ast_expr_vec_t args;
} call; } call;
// 数组下标 // 数组下标
@@ -277,16 +277,12 @@ struct scc_ast_expr {
scc_ast_expr_t *array; scc_ast_expr_t *array;
scc_ast_expr_t *index; scc_ast_expr_t *index;
} subscript; } subscript;
// 成员访问 // 成员访问 指针成员访问
struct { struct {
scc_ast_expr_t *base; scc_ast_expr_t *base;
const char *member_name; const char *name;
usize _target_idx;
} member; } member;
// 指针成员访问
struct {
scc_ast_expr_t *base;
const char *member_name;
} ptr_member;
// 类型转换 // 类型转换
struct { struct {
scc_ast_type_t *type; scc_ast_type_t *type;
@@ -310,6 +306,7 @@ struct scc_ast_expr {
// 标识符 // 标识符
struct { struct {
const char *name; const char *name;
scc_ast_decl_t *_target;
} identifier; } identifier;
}; };
}; };
@@ -334,21 +331,16 @@ struct scc_ast_stmt {
scc_ast_stmt_t *then_stmt; scc_ast_stmt_t *then_stmt;
scc_ast_stmt_t *opt_else_stmt; // stmt or null scc_ast_stmt_t *opt_else_stmt; // stmt or null
} if_stmt; } if_stmt;
// while 语句 // while do-while 语句
struct { struct {
scc_ast_expr_t *cond; scc_ast_expr_t *cond;
scc_ast_stmt_t *body; scc_ast_stmt_t *body;
} while_stmt; } while_stmt;
// do-while 语句
struct {
scc_ast_stmt_t *body;
scc_ast_expr_t *cond;
} do_while_stmt;
// for 语句 // for 语句
struct { struct {
scc_ast_type_t *init; // expr or decl or null scc_ast_type_t *init; // expr or decl or null
scc_ast_expr_t *cond; // 可为 null scc_ast_expr_t *cond; // 可为 null
scc_ast_expr_t *iter; // 可为 null scc_ast_expr_t *incr; // 可为 null
scc_ast_stmt_t *body; scc_ast_stmt_t *body;
} for_stmt; } for_stmt;
// switch 语句 // switch 语句
@@ -367,15 +359,15 @@ struct scc_ast_stmt {
} default_stmt; } default_stmt;
// break/continue // break/continue
struct { struct {
// 无额外字段
} jump; } jump;
// return 语句 // return 语句
struct { struct {
scc_ast_expr_t *expr; // 可为 NULL scc_ast_expr_t *expr; // 可为 null
} return_stmt; } return_stmt;
// goto 语句 // goto 语句
struct { struct {
const char *label; const char *label;
scc_ast_stmt_t *_target; // fill by sema
} goto_stmt; } goto_stmt;
// 标签语句 // 标签语句
struct { struct {
@@ -390,37 +382,32 @@ struct scc_ast_stmt {
*/ */
struct scc_ast_decl { struct scc_ast_decl {
scc_ast_node_t base; scc_ast_node_t base;
const char *name;
union { union {
// 变量声明 // 变量声明
struct { struct {
const char *name;
scc_ast_type_t *type; scc_ast_type_t *type;
scc_ast_expr_t *init; // 可为 NULL scc_ast_expr_t *init; // 可为 NULL
} var; } var;
// 函数声明 // 函数声明
struct { struct {
const char *name;
scc_ast_type_t *type; // 函数类型 scc_ast_type_t *type; // 函数类型
scc_ast_stmt_t *body; // 可为 null 表示只有声明 scc_ast_stmt_t *body; // 可为 null 表示只有声明
} func; } func;
// 参数声明 // 参数声明
struct { struct {
const char *name;
scc_ast_type_t *type; scc_ast_type_t *type;
} param; } param;
// 结构体/联合声明 // 结构体/联合声明
struct { struct {
const char *name;
scc_ast_decl_vec_t fields; scc_ast_decl_vec_t fields;
} record; } record;
// 枚举声明 // 枚举声明
struct { struct {
const char *name;
scc_ast_expr_vec_t enumerators; scc_ast_expr_vec_t enumerators;
} enumeration; } enumeration;
// typedef 声明 // typedef 声明
struct { struct {
const char *name;
scc_ast_type_t *type; scc_ast_type_t *type;
} typedef_decl; } typedef_decl;
}; };

View File

@@ -1,7 +1,416 @@
#ifndef __SCC_AST_H__ #ifndef __SCC_AST_H__
#define __SCC_AST_H__ #define __SCC_AST_H__
#include "ast_builtin.h"
#include "ast_def.h" #include "ast_def.h"
#include "ast_dump.h" #include "ast_dump.h"
// decls can be null but maybe warning
static inline void
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
scc_ast_decl_vec_t *decls) {
Assert(translation_unit != null);
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
translation_unit->base.loc = scc_pos_create();
if (decls == null) {
scc_vec_init(translation_unit->declarations);
} else {
translation_unit->declarations = *decls;
scc_vec_init(*decls);
}
}
// var_init can be null
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, const char *name,
scc_ast_expr_t *var_init) {
Assert(decl != null && name != null && type != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_VAR;
decl->name = name;
decl->var.type = type;
decl->var.init = var_init;
}
// body can be null
static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
scc_ast_type_t *type,
const char *name,
scc_ast_stmt_t *body) {
Assert(decl != null && name != null && type != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_FUNC;
decl->name = name;
decl->func.type = type;
Assert(type->base.type == SCC_AST_TYPE_FUNCTION);
decl->func.body = body;
}
// body can be null
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
scc_ast_type_t *type,
const char *name,
scc_ast_stmt_t *body) {
Assert(decl != null && name != null && type != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_PARAM;
decl->name = name;
decl->param.type = type;
}
// fields can be null
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move) {
Assert(decl != null && name != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_STRUCT;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->record.fields);
} else {
decl->record.fields = *fields_move;
scc_vec_init(*fields_move);
}
}
// fields can be null
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move) {
Assert(decl != null && name != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_UNION;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->record.fields);
} else {
decl->record.fields = *fields_move;
scc_vec_init(*fields_move);
}
}
// fields can be null
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_expr_vec_t *fields_move) {
Assert(decl != null && name != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_ENUM;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->enumeration.enumerators);
} else {
decl->enumeration.enumerators = *fields_move;
scc_vec_init(*fields_move);
}
}
static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_type_t *type) {
Assert(decl != null && name != null && type != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_TYPEDEF;
decl->name = name;
decl->typedef_decl.type = type;
}
// items can be null
static inline void
scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt,
scc_ast_block_item_vec_t *items_move) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_COMPOUND;
if (items_move == null) {
scc_vec_init(stmt->compound.block_items);
} else {
stmt->compound.block_items = *items_move;
scc_vec_init(*items_move);
}
}
// expr can be null
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_EXPR;
stmt->expr.expr = expr;
}
// opt_else can be null
static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *then,
scc_ast_stmt_t *opt_else) {
Assert(stmt != null && cond != null && then != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_IF;
stmt->if_stmt.cond = cond;
stmt->if_stmt.then_stmt = then;
stmt->if_stmt.opt_else_stmt = opt_else;
}
static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_DO_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
// FIXME
static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
scc_ast_type_t *init,
scc_ast_expr_t *cond,
scc_ast_expr_t *incr,
scc_ast_stmt_t *body) {
Assert(stmt != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_FOR;
stmt->for_stmt.init = init;
stmt->for_stmt.cond = cond;
stmt->for_stmt.incr = incr;
stmt->for_stmt.body = body;
}
static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_SWITCH;
stmt->switch_stmt.cond = cond;
stmt->switch_stmt.body = body;
}
static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.expr = cond;
stmt->case_stmt.stmt = body;
}
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
scc_ast_stmt_t *body) {
Assert(stmt != null && body != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_DEFAULT;
stmt->case_stmt.stmt = body;
}
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_BREAK;
}
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_CONTINUE;
}
// expr can be null
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_RETURN;
stmt->return_stmt.expr = expr;
}
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
const char *label) {
Assert(stmt != null && label != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_GOTO;
stmt->goto_stmt.label = label;
stmt->goto_stmt._target = null;
}
static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
const char *label,
scc_ast_stmt_t *body) {
Assert(stmt != null);
stmt->base.loc = scc_pos_create();
stmt->base.type = SCC_AST_STMT_LABEL;
stmt->label_stmt.label = label;
stmt->label_stmt.stmt = body;
}
static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *lhs,
scc_ast_expr_t *rhs) {
Assert(expr != null && lhs != null && rhs != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_BINARY;
expr->binary.op = op;
expr->binary.lhs = lhs;
expr->binary.rhs = rhs;
}
static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *operand) {
Assert(expr != null && operand != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_UNARY;
expr->unary.op = op;
expr->unary.operand = operand;
}
static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
scc_ast_expr_t *cond,
scc_ast_expr_t *then_expr,
scc_ast_expr_t *else_expr) {
Assert(expr != null && cond != null && then_expr != null &&
else_expr != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_COND;
expr->cond.cond = cond;
expr->cond.then_expr = then_expr;
expr->cond.else_expr = else_expr;
}
// args can be null
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
const char *name,
scc_ast_expr_vec_t *args) {
Assert(expr != null && name != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_CALL;
expr->call.name = name;
expr->call._target = null;
if (args == null) {
scc_vec_init(expr->call.args);
} else {
expr->call.args = *args;
}
}
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
scc_ast_expr_t *array,
scc_ast_expr_t *index) {
Assert(expr != null && array != null && index != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
expr->subscript.array = array;
expr->subscript.index = index;
}
static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
scc_ast_expr_t *object,
const char *member) {
Assert(expr != null && object != null && member != null);
expr->base.loc = scc_pos_create();
expr->base.type = type;
expr->member.base = object;
expr->member.name = member;
expr->member._target_idx = 0;
}
static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member);
}
static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member);
}
// SCC_AST_EXPR_CAST, // 类型转换
// SCC_AST_EXPR_SIZE_OF, // sizeof
// SCC_AST_EXPR_ALIGN_OF, // _Alignof
// SCC_AST_EXPR_COMPOUND_LITERAL, // 复合字面量
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
const char *value, cbool owned) {
Assert(expr != null && value != null);
expr->base.loc = scc_pos_create();
expr->base.type = type;
expr->literal.lexme = value;
expr->literal.owned = owned;
}
static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr,
const char *value,
cbool owned) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned);
}
static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr,
const char *value,
cbool owned) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned);
}
static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr,
const char *value,
cbool owned) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned);
}
static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
const char *value,
cbool owned) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned);
}
static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
const char *name) {
Assert(expr != null && name != null);
expr->base.loc = scc_pos_create();
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
expr->identifier.name = name;
expr->identifier._target = null;
}
// SCC_AST_TYPE_BUILTIN, // 内置类型
// SCC_AST_TYPE_POINTER, // 指针类型
// SCC_AST_TYPE_ARRAY, // 数组类型
// return_type and params can be null
static inline void scc_ast_type_function_init(scc_ast_type_t *type,
scc_ast_type_t *return_type,
scc_ast_decl_vec_t *params) {
Assert(type != null);
type->base.loc = scc_pos_create();
type->base.type = SCC_AST_TYPE_FUNCTION;
type->function.return_type = return_type;
if (params == null) {
scc_vec_init(type->function.param_types);
} else {
type->function.param_types = *params;
scc_vec_init(*params);
}
}
// SCC_AST_TYPE_STRUCT, // 结构体类型
// SCC_AST_TYPE_UNION, // 联合类型
// SCC_AST_TYPE_ENUM, // 枚举类型
// SCC_AST_TYPE_TYPEDEF, // typedef 类型
#endif /* __SCC_AST_H__ */ #endif /* __SCC_AST_H__ */

View File

@@ -0,0 +1,70 @@
#include <ast_builtin.h>
#define SCC_AST_BUILTIN_TYPE_HEADER \
.base.type = SCC_AST_TYPE_BUILTIN, .base.loc.col = 0, .base.loc.line = 0, \
.base.loc.name = "__scc_ast_builtin_type", .base.loc.offset = 0
scc_ast_type_t scc_ast_builtin_type_int = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_INT,
};
scc_ast_type_t scc_ast_builtin_type_long = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_LONG,
};
scc_ast_type_t scc_ast_builtin_type_long_long = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_LONG_LONG,
};
scc_ast_type_t scc_ast_builtin_type_short = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_SHORT,
};
scc_ast_type_t scc_ast_builtin_type_char = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_CHAR,
};
scc_ast_type_t scc_ast_builtin_type_void = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_VOID,
};
scc_ast_type_t scc_ast_builtin_type_bool = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_BOOL,
};
scc_ast_type_t scc_ast_builtin_type_float = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_FLOAT,
};
scc_ast_type_t scc_ast_builtin_type_double = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_DOUBLE,
};
scc_ast_type_t scc_ast_builtin_type_long_double = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_LONG_DOUBLE,
};
scc_ast_type_t scc_ast_builtin_type_complex_float = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT,
};
scc_ast_type_t scc_ast_builtin_type_complex_double = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE,
};
scc_ast_type_t scc_ast_builtin_type_complex_long_double = {
SCC_AST_BUILTIN_TYPE_HEADER,
.builtin.type = SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE,
};

View File

@@ -324,7 +324,12 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
} }
if (scc_vec_size(type->function.param_types) != 0) { if (scc_vec_size(type->function.param_types) != 0) {
scc_vec_foreach(type->function.param_types, i) { scc_vec_foreach(type->function.param_types, i) {
dump_type_impl(scc_vec_at(type->function.param_types, i), ctx); scc_ast_decl_t *param =
scc_vec_at(type->function.param_types, i);
if (param->name) {
// FIXME param name
}
dump_type_impl(param->param.type, ctx);
} }
} else { } else {
start_node_dump(&type->base, ctx); start_node_dump(&type->base, ctx);
@@ -435,7 +440,8 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
break; break;
case SCC_AST_EXPR_CALL: case SCC_AST_EXPR_CALL:
dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false); // dump_child_node((scc_ast_node_t *)expr->call._target, ctx, false);
PRINT_NODE(ctx, "%s", expr->call.name);
// 转储参数 // 转储参数
for (size_t i = 0; i < expr->call.args.size; i++) { for (size_t i = 0; i < expr->call.args.size; i++) {
dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx, dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx,
@@ -453,7 +459,7 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false); dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
// 打印成员访问信息 // 打印成员访问信息
scc_tree_print_indent(ctx); scc_tree_print_indent(ctx);
PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.member_name); PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.name);
scc_tree_dump_printf(ctx, "\n"); scc_tree_dump_printf(ctx, "\n");
break; break;
@@ -512,8 +518,8 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
return; return;
case SCC_AST_STMT_DO_WHILE: case SCC_AST_STMT_DO_WHILE:
end_node_dump(ctx); end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.body, ctx, false); dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.cond, ctx, true); dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, true);
return; return;
case SCC_AST_STMT_SWITCH: case SCC_AST_STMT_SWITCH:
end_node_dump(ctx); end_node_dump(ctx);
@@ -528,8 +534,8 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
if (stmt->for_stmt.cond) { if (stmt->for_stmt.cond) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false); dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false);
} }
if (stmt->for_stmt.iter) { if (stmt->for_stmt.incr) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.iter, ctx, false); dump_child_node((scc_ast_node_t *)stmt->for_stmt.incr, ctx, false);
} }
dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true); dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true);
return; return;
@@ -594,46 +600,8 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) {
return; return;
start_node_dump(&decl->base, ctx); start_node_dump(&decl->base, ctx);
if (decl->name) {
// 根据声明类型输出特定信息 PRINT_QUOTED_VALUE(ctx, decl->name);
switch (decl->base.type) {
case SCC_AST_DECL_VAR:
if (decl->var.name) {
PRINT_QUOTED_VALUE(ctx, decl->var.name);
}
break;
case SCC_AST_DECL_FUNC:
if (decl->func.name) {
PRINT_QUOTED_VALUE(ctx, decl->func.name);
}
break;
case SCC_AST_DECL_PARAM:
if (decl->param.name) {
PRINT_QUOTED_VALUE(ctx, decl->param.name);
}
break;
case SCC_AST_DECL_STRUCT:
if (decl->record.name) {
PRINT_QUOTED_VALUE(ctx, decl->record.name);
}
break;
case SCC_AST_DECL_UNION:
if (decl->record.name) {
PRINT_QUOTED_VALUE(ctx, decl->record.name);
}
break;
case SCC_AST_DECL_ENUM:
if (decl->enumeration.name) {
PRINT_QUOTED_VALUE(ctx, decl->enumeration.name);
}
break;
case SCC_AST_DECL_TYPEDEF:
if (decl->typedef_decl.name) {
PRINT_QUOTED_VALUE(ctx, decl->typedef_decl.name);
}
break;
default:
break;
} }
end_node_dump(ctx); end_node_dump(ctx);

View File

View File

@@ -293,7 +293,7 @@ void test_identifiers() {
// 超长标识符(假设缓冲区足够) // 超长标识符(假设缓冲区足够)
char long_id[1024]; char long_id[1024];
memset(long_id, 'a', sizeof(long_id) - 1); scc_memset(long_id, 'a', sizeof(long_id) - 1);
long_id[sizeof(long_id) - 1] = '\0'; long_id[sizeof(long_id) - 1] = '\0';
TEST_TOKEN(long_id, SCC_TOK_IDENT); TEST_TOKEN(long_id, SCC_TOK_IDENT);
} }

View File

@@ -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)); scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
/* /*
(6.7.5) declarator: (6.7.5) declarator:
pointeropt direct-declarator pointeropt direct-declarator
@@ -203,18 +202,14 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
direct-declarator ( identifier-listopt ) direct-declarator ( identifier-listopt )
*/ */
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
// TODO
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
decl->base.type = SCC_AST_DECL_VAR; scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
decl->var.type = type; null);
decl->var.name = scc_cstring_as_cstr(&tok.lexeme);
decl->var.init = null;
goto RETURN; goto RETURN;
} else if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { } else if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
decl->base.type = SCC_AST_DECL_VAR; scc_ast_expr_t *init = scc_parse_expression(parser);
decl->var.type = type; scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
decl->var.name = scc_cstring_as_cstr(&tok.lexeme); init);
decl->var.init = scc_parse_expression(parser);
goto RETURN; goto RETURN;
} }
// TODO // TODO
@@ -223,13 +218,11 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
// function decl // function decl
decl->base.type = SCC_AST_DECL_FUNC; 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 = scc_malloc(sizeof(scc_ast_type_t));
decl->func.type->base.type = SCC_AST_TYPE_FUNCTION; decl->func.type->base.type = SCC_AST_TYPE_FUNCTION;
scc_vec_init(decl->func.type->function.param_types); scc_vec_init(decl->func.type->function.param_types);
decl->func.type->function.return_type = type; decl->func.type->function.return_type = type;
// TODO
decl->func.type->function.is_variadic = false;
// TODO param type // TODO param type
scc_parser_consume_if(parser, SCC_TOK_VOID); scc_parser_consume_if(parser, SCC_TOK_VOID);

View File

@@ -760,7 +760,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
scc_lexer_tok_drop(&lp); scc_lexer_tok_drop(&lp);
scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL); 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); 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( 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);
if (op_tok.type == SCC_TOK_DOT) { member->member.base = left;
member->member.base = left; member->member.name = name;
member->member.member_name = name;
} else {
member->ptr_member.base = left;
member->ptr_member.member_name = name;
}
scc_lexer_tok_drop(&op_tok); scc_lexer_tok_drop(&op_tok);
left = member; left = member;
break; break;

View File

@@ -51,9 +51,9 @@ A.2.3 Statements
#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));
Assert(stmt != null); if (stmt == null) {
stmt->base.type = SCC_AST_UNKNOWN; LOG_FATAL("Out of memory");
stmt->base.loc = scc_pos_create(); }
return stmt; 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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null); Assert(stmt != null);
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement);
stmt->base.type = SCC_AST_STMT_LABEL;
stmt->label_stmt.label = scc_cstring_as_cstr(&tok.lexeme);
stmt->label_stmt.stmt = statement;
return stmt; 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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null); scc_ast_stmt_case_init(stmt, expr, statement);
stmt->case_stmt.expr = expr;
stmt->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.stmt = statement;
return stmt; return stmt;
} }
@@ -134,11 +128,9 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
if (statement == null) { if (statement == null) {
Panic("expect stmt"); 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
return null; return null;
} }
scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_block_item_vec_t block_items;
stmt->base.type = SCC_AST_STMT_COMPOUND; scc_vec_init(block_items);
scc_vec_init(stmt->compound.block_items);
while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) { while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
/// TODO /// TODO
// scc_parse_is_decl(); // scc_parse_is_decl();
@@ -160,12 +151,15 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
} }
if (ret == null) { if (ret == null) {
LOG_ERROR("Invalid statement"); LOG_ERROR("Invalid statement");
// TODO // TODO free
scc_free(stmt); parser->errcode = 1;
return null; 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; 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_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *statement = scc_parse_statement(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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_IF; scc_ast_stmt_if_init(stmt, expression, statement, opt_else);
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;
}
return stmt; 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 *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_SWITCH; scc_ast_stmt_switch_init(stmt, expression, statement);
stmt->switch_stmt.cond = expression;
stmt->switch_stmt.body = statement;
return stmt; 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 *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_WHILE; scc_ast_stmt_while_init(stmt, expression, statement);
stmt->while_stmt.cond = expression;
stmt->while_stmt.body = statement;
return stmt; 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_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_DO_WHILE; scc_ast_stmt_do_while_init(stmt, expression, statement);
stmt->do_while_stmt.cond = expression;
stmt->do_while_stmt.body = statement;
return stmt; return stmt;
} }
@@ -255,15 +243,17 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
LOG_ERROR("Expected '(' before like `( expression )` ."); LOG_ERROR("Expected '(' before like `( expression )` .");
} }
scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_type_t *init = null;
stmt->base.type = SCC_AST_STMT_FOR; scc_ast_expr_t *cond = null;
scc_ast_expr_t *incr = null;
scc_ast_stmt_t *body = null;
// TODO use decl or expr // TODO use decl or expr
stmt->for_stmt.init = (scc_ast_type_t *)scc_parse_expression(parser); init = (scc_ast_type_t *)scc_parse_expression(parser);
if (stmt->for_stmt.init == null) { if (init == null) {
stmt->for_stmt.init = (scc_ast_type_t *)scc_parse_declaration(parser); 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."); 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."); 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon in for statement."); 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
LOG_ERROR("Expected ')' after like `( expression )` ."); 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; 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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) { if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
stmt->base.type = SCC_AST_STMT_GOTO;
scc_lexer_tok_t tok = {0}; scc_lexer_tok_t tok = {0};
if (scc_parser_next_consume(parser, &tok)) { 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 { } else {
LOG_ERROR("Expected label after goto."); LOG_ERROR("Expected label after goto.");
} }
} else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) { } 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)) { } 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)) { } else if (scc_parser_consume_if(parser, SCC_TOK_RETURN)) {
stmt->base.type = SCC_AST_STMT_RETURN; scc_ast_stmt_return_init(stmt, scc_parse_expression(parser));
stmt->return_stmt.expr = scc_parse_expression(parser);
} else { } else {
UNREACHABLE(); 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) { 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)) { 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon after expression."); LOG_ERROR("Expected semicolon after expression.");
} }

View File

@@ -234,7 +234,11 @@ cbool scc_parse_is_storage_class_start(scc_parser_t *parser) {
return false; return false;
} }
} }
scc_ast_type_t *scc_parse_type(scc_parser_t *parser) { 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); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
scc_ast_type_t *ret = null; scc_ast_type_t *ret = null;
if (tok_ptr->type == SCC_TOK_INT) { if (tok_ptr->type == SCC_TOK_INT) {

View File

@@ -17,7 +17,7 @@ static scc_ast_node_t *process_input(const char *input,
scc_lexer_t lexer; scc_lexer_t lexer;
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); 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_t parser;
scc_parser_init(&parser, tok_ring, null); scc_parser_init(&parser, tok_ring, null);
@@ -69,516 +69,455 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
} while (0); } while (0);
static void test_parser_unit(void) { static void test_parser_unit(void) {
scc_ast_decl_t int_decl = { // 1. 变量声明 int a;
.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);
{ {
scc_ast_node_t *items[] = { scc_ast_decl_t int_decl;
(scc_ast_node_t *)&(scc_ast_stmt_t){ scc_ast_decl_val_init(
.base.type = SCC_AST_STMT_RETURN, &int_decl, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null);
.return_stmt.expr = SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration);
&(scc_ast_expr_t){ }
.base.type = SCC_AST_EXPR_INT_LITERAL,
.literal.lexme = "65536", // 2. 函数声明 int main(void) {}
}, {
}, // 构造函数类型:返回 int参数为空
}; scc_ast_type_t func_type;
scc_ast_decl_t func_decl = { scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int,
.base.type = SCC_AST_DECL_FUNC, null); // 无参数,非可变参数
.func.name = "main",
.func.body = // 构造复合语句块(空)
&(scc_ast_stmt_t){ scc_ast_stmt_t compound;
.base.type = SCC_AST_STMT_COMPOUND, scc_ast_stmt_compound_init(&compound, null);
.compound.block_items.cap = 1,
.compound.block_items.size = 1, // 构造函数声明
.compound.block_items.data = items, scc_ast_decl_t func_decl;
}, scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
.func.type =
&(scc_ast_type_t){ SCC_CHECK_AST(&func_decl.base, "int main(void) {}",
.base.type = SCC_AST_TYPE_FUNCTION, scc_parse_declaration);
.function.is_variadic = false, }
.function.param_types = {0},
.function.return_type = // 3. 翻译单元包含一个函数定义
&(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, {
.builtin.type = scc_ast_type_t func_type;
SCC_AST_BUILTIN_TYPE_INT}, scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, null);
},
}; scc_ast_stmt_t compound;
scc_ast_decl_t *decls[] = {&func_decl}; scc_ast_stmt_compound_init(&compound, null);
scc_ast_translation_unit_t tu = {
.base.type = SCC_AST_TRANSLATION_UNIT, scc_ast_decl_t func_decl;
.declarations.cap = 1, scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
.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_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_CHECK_AST(&tu.base, "int main(void) { return 65536; }",
scc_parse_translation_unit); scc_parse_translation_unit);
} }
// 5. 多语句函数(复杂示例)
{ {
// 修复后的测试用例:正确表示多语句函数 // 变量声明 int a;
// 创建变量声明: int a; scc_ast_decl_t a_decl;
scc_ast_type_t a_type = {.base.type = SCC_AST_TYPE_BUILTIN, scc_ast_decl_val_init(&a_decl, &scc_ast_builtin_type_int, "a", null);
.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 b; // 变量声明 int b;
scc_ast_type_t b_type = {.base.type = SCC_AST_TYPE_BUILTIN, scc_ast_decl_t b_decl;
.builtin.type = SCC_AST_BUILTIN_TYPE_INT}; scc_ast_decl_val_init(&b_decl, &scc_ast_builtin_type_int, "b", null);
scc_ast_decl_t b_decl = {.base.type = SCC_AST_DECL_VAR,
.var.name = "b",
.var.type = &b_type};
// 创建表达式: 1 + 2 * 3 // 表达式 1 + 2 * 3
scc_ast_expr_t expr1_3 = {.base.type = SCC_AST_EXPR_INT_LITERAL, scc_ast_expr_t lit1, lit2, lit3, mul, add;
.literal.lexme = "3"}; scc_ast_expr_literal_int_init(&lit1, "1", false);
scc_ast_expr_t expr1_2 = {.base.type = SCC_AST_EXPR_INT_LITERAL, scc_ast_expr_literal_int_init(&lit2, "2", false);
.literal.lexme = "2"}; scc_ast_expr_literal_int_init(&lit3, "3", false);
scc_ast_expr_t expr1_mul = {.base.type = SCC_AST_EXPR_BINARY, scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3);
.binary.op = SCC_AST_OP_MUL, scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &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};
// 创建赋值语句: a = 1 + 2 * 3; // 赋值 a = 1 + 2 * 3;
scc_ast_expr_t a_expr1 = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_t a_ref1, assign1;
.identifier.name = "a"}; scc_ast_expr_identifier_init(&a_ref1, "a");
scc_ast_expr_t assign1 = {.base.type = SCC_AST_EXPR_BINARY, scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add);
.binary.op = SCC_AST_OP_ASSIGN, scc_ast_stmt_t assign1_stmt;
.binary.lhs = &a_expr1, scc_ast_stmt_expr_init(&assign1_stmt, &assign1);
.binary.rhs = &expr1_add};
scc_ast_stmt_t assign1_stmt = {.base.type = SCC_AST_STMT_EXPR,
.expr.expr = &assign1};
// 创建赋值语句: b = 7; // 赋值 b = 7;
scc_ast_expr_t expr2_7 = {.base.type = SCC_AST_EXPR_INT_LITERAL, scc_ast_expr_t lit7;
.literal.lexme = "7"}; scc_ast_expr_literal_int_init(&lit7, "7", false);
scc_ast_expr_t b_expr1 = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_t b_ref1, assign2;
.identifier.name = "b"}; scc_ast_expr_identifier_init(&b_ref1, "b");
scc_ast_expr_t assign2 = {.base.type = SCC_AST_EXPR_BINARY, scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7);
.binary.op = SCC_AST_OP_ASSIGN, scc_ast_stmt_t assign2_stmt;
.binary.lhs = &b_expr1, scc_ast_stmt_expr_init(&assign2_stmt, &assign2);
.binary.rhs = &expr2_7};
scc_ast_stmt_t assign2_stmt = {.base.type = SCC_AST_STMT_EXPR,
.expr.expr = &assign2};
// 创建表达式: a - b + 1 // 表达式 a - b + 1
scc_ast_expr_t a_expr2 = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_t a_ref2, b_ref2, sub, add2, lit1_2;
.identifier.name = "a"}; scc_ast_expr_identifier_init(&a_ref2, "a");
scc_ast_expr_t b_expr2 = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_identifier_init(&b_ref2, "b");
.identifier.name = "b"}; scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2);
scc_ast_expr_t sub_expr = {.base.type = SCC_AST_EXPR_BINARY, scc_ast_expr_literal_int_init(&lit1_2, "1", false);
.binary.op = SCC_AST_OP_SUB, scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2);
.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 = a - b + 1; // 赋值 a = a - b + 1;
scc_ast_expr_t a_expr3 = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_t a_ref3, assign3;
.identifier.name = "a"}; scc_ast_expr_identifier_init(&a_ref3, "a");
scc_ast_expr_t assign3 = {.base.type = SCC_AST_EXPR_BINARY, scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2);
.binary.op = SCC_AST_OP_ASSIGN, scc_ast_stmt_t assign3_stmt;
.binary.lhs = &a_expr3, scc_ast_stmt_expr_init(&assign3_stmt, &assign3);
.binary.rhs = &add_expr};
scc_ast_stmt_t assign3_stmt = {.base.type = SCC_AST_STMT_EXPR,
.expr.expr = &assign3};
// 创建return语句: return a; // return a;
scc_ast_expr_t return_expr = {.base.type = SCC_AST_EXPR_IDENTIFIER, scc_ast_expr_t a_ref4;
.identifier.name = "a"}; scc_ast_expr_identifier_init(&a_ref4, "a");
scc_ast_stmt_t return_stmt = {.base.type = SCC_AST_STMT_RETURN, scc_ast_stmt_t ret_stmt;
.return_stmt.expr = &return_expr}; scc_ast_stmt_return_init(&ret_stmt, &a_ref4);
// 创建复合语句块 // 复合语句块,按顺序放入
scc_ast_node_t *items[] = { scc_ast_block_item_vec_t items;
(scc_ast_node_t *)&a_decl, (scc_ast_node_t *)&b_decl, scc_vec_init(items);
(scc_ast_node_t *)&assign1_stmt, (scc_ast_node_t *)&assign2_stmt, scc_vec_push(items, (scc_ast_node_t *)&a_decl);
(scc_ast_node_t *)&assign3_stmt, (scc_ast_node_t *)&return_stmt}; 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, scc_ast_stmt_t compound;
.builtin.type = SCC_AST_BUILTIN_TYPE_INT}; scc_ast_stmt_compound_init(&compound, &items);
scc_ast_type_t func_type = {.base.type = SCC_AST_TYPE_FUNCTION, // 函数类型
.function.is_variadic = false, scc_ast_type_t func_type;
.function.param_types = {0}, scc_ast_type_function_init(
.function.return_type = &return_type}; &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
scc_ast_decl_t func_decl = { scc_ast_decl_t func_decl;
.base.type = SCC_AST_DECL_FUNC, scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
.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 *decls[] = {&func_decl}; scc_ast_decl_vec_t tu_decls;
scc_ast_translation_unit_t tu = {.base.type = SCC_AST_TRANSLATION_UNIT, scc_vec_init(tu_decls);
.declarations.cap = 1, scc_vec_push(tu_decls, &func_decl);
.declarations.size = 1,
.declarations.data = decls};
SCC_CHECK_AST(&tu.base, scc_ast_translation_unit_t tu;
"int main() {\n" scc_ast_translation_unit_init(&tu, &tu_decls);
" int a;\n"
" int b;\n" const char *input = "int main() {\n"
" a = 1 + 2 * 3;\n" " int a;\n"
" b = 7;\n" " int b;\n"
" a = a - b + 1;\n" " a = 1 + 2 * 3;\n"
" return a;\n" " b = 7;\n"
"}\n", " a = a - b + 1;\n"
scc_parse_translation_unit); " 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) { 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_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_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_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); SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression);
} }
// 2. 后缀表达式 // 2. 后缀表达式
{ {
// 数组下标a[10] // 数组下标 a[10]
scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t a, index, subscript;
scc_ast_expr_t index = make_int_literal("10"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t subscript = {.base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT}; scc_ast_expr_literal_int_init(&index, "10", false);
subscript.subscript.array = &a; scc_ast_expr_array_subscript_init(&subscript, &a, &index);
subscript.subscript.index = &index;
SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression);
// 函数调用f() // 函数调用 f()
scc_ast_expr_t f = make_identifier("f"); scc_ast_expr_t f;
scc_ast_expr_t call = {.base.type = SCC_AST_EXPR_CALL}; scc_ast_expr_identifier_init(&f, "f");
call.call.callee = &f;
scc_ast_expr_vec_t args; scc_ast_expr_vec_t args;
scc_vec_init(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); SCC_CHECK_AST(&call.base, "f()", scc_parse_expression);
// 函数调用带参数f(1, x) // 函数调用带参数 f(1, x)
scc_ast_expr_t f2 = make_identifier("f"); scc_ast_expr_t arg1, arg2;
scc_ast_expr_t arg1 = make_int_literal("1"); scc_ast_expr_literal_int_init(&arg1, "1", false);
scc_ast_expr_t arg2 = make_identifier("x"); scc_ast_expr_identifier_init(&arg2, "x");
scc_ast_expr_vec_t args2; scc_ast_expr_vec_t args2;
scc_vec_init(args2); scc_vec_init(args2);
scc_vec_push(args2, &arg1); scc_vec_push(args2, &arg1);
scc_vec_push(args2, &arg2); scc_vec_push(args2, &arg2);
scc_ast_expr_t call2 = {.base.type = SCC_AST_EXPR_CALL}; scc_ast_expr_t call2;
call2.call.callee = &f2; scc_ast_expr_call_init(&call2, "f", &args2);
call2.call.args = args2;
SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression);
// 成员访问 . 和 -> // 成员访问 .
scc_ast_expr_t s = make_identifier("s"); scc_ast_expr_t s, dot;
scc_ast_expr_t dot = {.base.type = SCC_AST_EXPR_MEMBER}; scc_ast_expr_identifier_init(&s, "s");
dot.member.base = &s; scc_ast_expr_member_init(&dot, &s, "field");
dot.member.member_name = "field";
SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression); 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}; scc_ast_expr_t p, arrow;
arrow.ptr_member.base = &p; scc_ast_expr_identifier_init(&p, "p");
arrow.ptr_member.member_name = "field"; scc_ast_expr_ptr_member_init(&arrow, &p, "field");
SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression); SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression);
// 后缀 ++/-- // 后缀 ++/--
scc_ast_expr_t x = make_identifier("x"); scc_ast_expr_t x, post_inc, post_dec;
scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &x); 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_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); SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression);
// 复合字面量 TODO: (int){1,2} 需要更复杂的构造,暂略
// SCC_CHECK_AST(..., "(int){1,2}", scc_parse_expression);
} }
// 3. 一元表达式 // 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_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_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_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_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_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_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_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); SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression);
// sizeof 两种形式
// sizeof 表达式 // sizeof 表达式
scc_ast_expr_t sizeof_expr = {.base.type = SCC_AST_EXPR_SIZE_OF}; // TODO
sizeof_expr.attr_of.expr = &x; // scc_ast_expr_t sizeof_expr;
SCC_CHECK_AST(&sizeof_expr.base, "sizeof x", scc_parse_expression); // scc_ast_expr_sizeof_expr_init(&sizeof_expr, &x);
// SCC_CHECK_AST(&sizeof_expr.base, "sizeof x", scc_parse_expression);
// sizeof(类型名) 需要构造类型节点暂时略用TODO
// SCC_CHECK_AST(..., "sizeof(int)", scc_parse_expression);
} }
// 4. 类型转换 // 4. 类型转换(示例: (int)x
{ {
// (int)x // scc_ast_type_t
// 需要构造类型节点这里简化用TODO // int_type; // 使用内置类型全局变量即可,但类型转换需要一个类型节点
// 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 = // // TODO
// SCC_AST_EXPR_CAST }; cast.cast.type = &int_type; cast.cast.expr = // scc_ast_expr_t x;
// &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. 二元运算符优先级
{ {
scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t a, b, c, d;
scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t c = make_identifier("c"); scc_ast_expr_identifier_init(&b, "b");
scc_ast_expr_t d = make_identifier("d"); scc_ast_expr_identifier_init(&c, "c");
scc_ast_expr_identifier_init(&d, "d");
// 乘除模优先级高于加减 // a * b + c
scc_ast_expr_t mul = make_binary(SCC_AST_OP_MUL, &a, &b); scc_ast_expr_t mul, add;
scc_ast_expr_t add = make_binary(SCC_AST_OP_ADD, &mul, &c); 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); SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression);
// 左结合性 a - b - c => (a - b) - c // a - b - c => (a - b) - c
scc_ast_expr_t sub1 = make_binary(SCC_AST_OP_SUB, &a, &b); scc_ast_expr_t sub1, sub2;
scc_ast_expr_t sub2 = make_binary(SCC_AST_OP_SUB, &sub1, &c); 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_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression);
// 移位 // a << b
scc_ast_expr_t shift = make_binary(SCC_AST_OP_LEFT_SHIFT, &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_CHECK_AST(&shift.base, "a << b", scc_parse_expression);
// 关系 // a < b
scc_ast_expr_t lt = make_binary(SCC_AST_OP_LESS, &a, &b); scc_ast_expr_t lt;
scc_ast_expr_binary_init(&lt, SCC_AST_OP_LESS, &a, &b);
SCC_CHECK_AST(&lt.base, "a < b", scc_parse_expression); SCC_CHECK_AST(&lt.base, "a < b", scc_parse_expression);
// 相等 // a == b
scc_ast_expr_t eq = make_binary(SCC_AST_OP_EQUAL, &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_CHECK_AST(&eq.base, "a == b", scc_parse_expression);
// 按位与、异或、或的优先级:& 高于 ^ 高于 | // a & b ^ c | d
scc_ast_expr_t bitand = make_binary(SCC_AST_OP_BITWISE_AND, &a, &b); scc_ast_expr_t bitand, bitxor, bitor;
scc_ast_expr_t bitxor = scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b);
make_binary(SCC_AST_OP_BITWISE_XOR, &bitand, &c); scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c);
scc_ast_expr_t bitor = make_binary(SCC_AST_OP_BITWISE_OR, &bitxor, &d); 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_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression);
// 逻辑与、或:&& 高于 || // a && b || c
scc_ast_expr_t logand = make_binary(SCC_AST_OP_LOGICAL_AND, &a, &b); scc_ast_expr_t logand, logor;
scc_ast_expr_t logor = make_binary(SCC_AST_OP_LOGICAL_OR, &logand, &c); 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); SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression);
} }
// 6. 三元运算符 // 6. 三元运算符
{ {
scc_ast_expr_t cond = make_identifier("a"); scc_ast_expr_t a, b, c;
scc_ast_expr_t then_expr = make_identifier("b"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t else_expr = make_identifier("c"); scc_ast_expr_identifier_init(&b, "b");
scc_ast_expr_t cond_expr = scc_ast_expr_identifier_init(&c, "c");
make_conditional(&cond, &then_expr, &else_expr);
SCC_CHECK_AST(&cond_expr.base, "a ? b : c", scc_parse_expression);
// 右结合性 a ? b : c ? d : e => a ? b : (c ? d : e) // a ? b : c
scc_ast_expr_t cond2 = make_identifier("c"); scc_ast_expr_t cond1;
scc_ast_expr_t then2 = make_identifier("d"); scc_ast_expr_cond_init(&cond1, &a, &b, &c);
scc_ast_expr_t else2 = make_identifier("e"); SCC_CHECK_AST(&cond1.base, "a ? b : c", scc_parse_expression);
scc_ast_expr_t inner_cond = make_conditional(&cond2, &then2, &else2);
scc_ast_expr_t outer_cond = // a ? b : c ? d : e => a ? b : (c ? d : e)
make_conditional(&cond, &then_expr, &inner_cond); scc_ast_expr_t d, e;
SCC_CHECK_AST(&outer_cond.base, "a ? b : c ? d : e", scc_ast_expr_identifier_init(&d, "d");
scc_parse_expression); 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 a, b, c;
scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t c = make_identifier("c"); scc_ast_expr_identifier_init(&b, "b");
scc_ast_expr_t int_lit = make_int_literal("42"); scc_ast_expr_identifier_init(&c, "c");
scc_ast_expr_t assign1 = make_binary(SCC_AST_OP_ASSIGN, &b, &c); scc_ast_expr_t lit42;
scc_ast_expr_t assign2 = scc_ast_expr_literal_int_init(&lit42, "42", false);
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 assign3 = make_binary(SCC_AST_OP_ASSIGN, &a, &int_lit); // a = b = c
SCC_CHECK_AST(&assign3.base, "a = 42", scc_parse_expression); 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); // a = 42
scc_ast_expr_t assign5 = scc_ast_expr_t assign1;
make_binary(SCC_AST_OP_ADD, &assign4, &int_lit); scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a, &lit42);
scc_ast_expr_t assign6 = make_binary(SCC_AST_OP_ASSIGN, &a, &assign5); SCC_CHECK_AST(&assign1.base, "a = 42", scc_parse_expression);
SCC_CHECK_AST(&assign6.base, "a = a - b + 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); SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression);
} }
// 8. 逗号运算符 // 8. 逗号运算符
{ {
scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t a, b;
scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t comma1 = make_binary(SCC_AST_OP_COMMA, &a, &b); scc_ast_expr_identifier_init(&b, "b");
SCC_CHECK_AST(&comma1.base, "a, b", scc_parse_expression); 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 a, b, c, d;
scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_identifier_init(&a, "a");
scc_ast_expr_t c = make_identifier("c"); scc_ast_expr_identifier_init(&b, "b");
scc_ast_expr_t d = make_identifier("d"); scc_ast_expr_identifier_init(&c, "c");
scc_ast_expr_identifier_init(&d, "d");
// a + b * c - 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 mul, add, sub;
scc_ast_expr_t add = make_binary(SCC_AST_OP_ADD, &a, &mul); scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c);
scc_ast_expr_t sub = make_binary(SCC_AST_OP_SUB, &add, &d); 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); SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression);
// *p++ => *(p++) // *p++
scc_ast_expr_t p = make_identifier("p"); scc_ast_expr_t p, post_inc, deref;
scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &p); scc_ast_expr_identifier_init(&p, "p");
scc_ast_expr_t deref = make_unary(SCC_AST_OP_INDIRECTION, &post_inc); 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); SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression);
} }
} }
@@ -586,5 +525,5 @@ static void test_parser_expression(void) {
TEST_LIST = { TEST_LIST = {
{"parser_unit", test_parser_unit}, {"parser_unit", test_parser_unit},
{"parser_expression", test_parser_expression}, {"parser_expression", test_parser_expression},
{NULL, NULL}, {null, null},
}; };

View File

@@ -16,7 +16,7 @@ static cbool process_input(const char *input, scc_cstring_t *output) {
scc_pproc_t pp; scc_pproc_t pp;
scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true));
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8); scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true);
*output = scc_cstring_from_cstr(""); *output = scc_cstring_from_cstr("");
scc_lexer_tok_t tok; scc_lexer_tok_t tok;
while (1) { while (1) {

View File

@@ -16,8 +16,8 @@ typedef enum {
SCC_FILE_WRITE, SCC_FILE_WRITE,
SCC_FILE_APPEND, SCC_FILE_APPEND,
} scc_fmode_t; } scc_fmode_t;
#define scc_stdout 1 #define scc_stdout ((scc_file_t)1)
#define scc_stderr 2 #define scc_stderr ((scc_file_t)2)
scc_file_t scc_fopen(const char *path, scc_fmode_t mode); scc_file_t scc_fopen(const char *path, scc_fmode_t mode);
void scc_fclose(scc_file_t file); void scc_fclose(scc_file_t file);
usize scc_fsize(scc_file_t file); usize scc_fsize(scc_file_t file);

View File

@@ -150,4 +150,11 @@ typedef size_t usize;
(vec).size = (vec).cap = 0; \ (vec).size = (vec).cap = 0; \
} while (0) } while (0)
#define scc_vec_unsafe_from_static_array(vec, array) \
do { \
(vec).size = sizeof(array) / sizeof((array)[0]); \
(vec).cap = (vec).size; \
(vec).data = array; \
} while (0)
#endif /* __SCC_CORE_VEC_H__ */ #endif /* __SCC_CORE_VEC_H__ */

View File

@@ -72,9 +72,9 @@ int scc_fprintf(scc_file_t file, const char *format, ...) {
int scc_vfprintf(scc_file_t file, const char *format, va_list args) { int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
char buf[4096] = {0}; char buf[4096] = {0};
int size = vsnprintf_(buf, sizeof(buf), format, args); int size = vsnprintf_(buf, sizeof(buf), format, args);
if (file == (scc_file_t)scc_stdout) { if (file == scc_stdout) {
scc_pal_write(buf, size); scc_pal_write(buf, size);
} else if (file == (scc_file_t)scc_stderr) { } else if (file == scc_stderr) {
scc_pal_ewrite(buf, size); scc_pal_ewrite(buf, size);
} else { } else {
scc_pal_fwrite(file, buf, size); scc_pal_fwrite(file, buf, size);

View File

@@ -158,30 +158,22 @@ static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) {
} }
} }
static void print_file(scc_lexer_tok_ring_t *ring, const char *file_name) { static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) {
scc_lexer_tok_t tok = {0}; scc_lexer_tok_t tok = {0};
int ret = 0; int ret = 0;
scc_file_t fp = null;
cbool is_stdout = scc_strcmp(file_name, "-") == 0;
if (!is_stdout) {
fp = scc_fopen(file_name, SCC_FILE_WRITE);
if (fp == null) {
LOG_FATAL("Failed to open file %s", file_name);
return;
}
}
while (1) { while (1) {
scc_ring_next_consume(*ring, tok, ret); scc_ring_next_consume(*ring, tok, ret);
if (ret == false || tok.type == SCC_TOK_EOF) { if (ret == false || tok.type == SCC_TOK_EOF) {
break; break;
} }
if (is_stdout) { if (fp == scc_stdout) {
scc_printf("%s", scc_cstring_as_cstr(&tok.lexeme)); scc_printf("%s", scc_cstring_as_cstr(&tok.lexeme));
} else { } else {
usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme), usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme),
scc_cstring_len(&tok.lexeme)); scc_cstring_len(&tok.lexeme));
if (ret != scc_cstring_len(&tok.lexeme)) { if (ret != scc_cstring_len(&tok.lexeme)) {
LOG_FATAL("Failed to write to file %s", file_name); LOG_FATAL("Failed to write to file");
} }
} }
scc_lexer_tok_drop(&tok); scc_lexer_tok_drop(&tok);
@@ -225,6 +217,18 @@ int main(int argc, const char **argv, const char **envp) {
} }
scc_argparse_drop(&argparse); scc_argparse_drop(&argparse);
scc_file_t fp = null;
if (config.output_file) {
cbool is_stdout = scc_strcmp(config.output_file, "-") == 0;
if (!is_stdout) {
fp = scc_fopen(config.output_file, SCC_FILE_WRITE);
if (fp == null) {
LOG_FATAL("Failed to open file %s", config.output_file);
return 1;
}
}
}
scc_sstream_t sstream; scc_sstream_t sstream;
if (scc_sstream_init(&sstream, config.input_file, 1024)) { if (scc_sstream_init(&sstream, config.input_file, 1024)) {
return 0; return 0;
@@ -233,12 +237,12 @@ int main(int argc, const char **argv, const char **envp) {
scc_lexer_t lexer; scc_lexer_t lexer;
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream)); scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
if (config.emit_lex) { if (config.emit_lex) {
scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring( scc_lexer_tok_ring_t *tok_ring =
&lexer, 8, config.output_file == null ? false : true); scc_lexer_to_ring(&lexer, 8, fp == null ? false : true);
if (config.output_file == null) { if (fp == null) {
print_ring(tok_ring, config.verbose); print_ring(tok_ring, config.verbose);
} else { } else {
print_file(tok_ring, config.output_file); print_file(tok_ring, fp);
} }
return 0; return 0;
} }
@@ -260,7 +264,7 @@ int main(int argc, const char **argv, const char **envp) {
if (config.output_file == null) { if (config.output_file == null) {
print_ring(tok_ring, config.verbose); print_ring(tok_ring, config.verbose);
} else { } else {
print_file(tok_ring, config.output_file); print_file(tok_ring, fp);
} }
return 0; return 0;
} }
@@ -271,15 +275,20 @@ int main(int argc, const char **argv, const char **envp) {
scc_ast_translation_unit_t *translation_unit = scc_ast_translation_unit_t *translation_unit =
scc_parse_translation_unit(&parser); scc_parse_translation_unit(&parser);
scc_parser_drop(&parser); // scc_parser_drop(&parser);
scc_pproc_drop(&pproc); // scc_pproc_drop(&pproc);
scc_lexer_drop(&lexer); // scc_lexer_drop(&lexer);
scc_sstream_drop(&sstream); // scc_sstream_drop(&sstream);
if (config.emit_ast) { if (config.emit_ast) {
scc_tree_dump_ctx_t tree_dump; scc_tree_dump_ctx_t tree_dump;
scc_tree_dump_ctx_init(&tree_dump, true, (void *)scc_fprintf, if (fp == null) {
(void *)scc_stdout); scc_tree_dump_ctx_init(&tree_dump, true, (void *)scc_fprintf,
(void *)scc_stdout);
} else {
scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf,
(void *)fp);
}
scc_ast_dump_node(&tree_dump, (scc_ast_node_t *)translation_unit); scc_ast_dump_node(&tree_dump, (scc_ast_node_t *)translation_unit);
scc_tree_dump_ctx_drop(&tree_dump); scc_tree_dump_ctx_drop(&tree_dump);
return 0; return 0;