Compare commits
2 Commits
2d1032c363
...
8fcfeda14e
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fcfeda14e | |||
| c99f64708e |
@@ -52,6 +52,7 @@ typedef enum {
|
||||
SCC_AST_EXPR_ALIGN_OF, // _Alignof
|
||||
SCC_AST_EXPR_COMPOUND, // 复合字面量
|
||||
SCC_AST_EXPR_LVALUE, // 右值
|
||||
SCC_AST_EXPR_BUILTIN, // 内置表达式
|
||||
// 字面量
|
||||
SCC_AST_EXPR_INT_LITERAL, // 整数字面量
|
||||
SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
|
||||
@@ -258,6 +259,13 @@ typedef enum scc_ast_expr_op {
|
||||
SCC_AST_OP_PTR_MEMBER_ACCESS, // ->
|
||||
} scc_ast_expr_op_t;
|
||||
|
||||
typedef enum {
|
||||
SCC_AST_EXPR_BUILTIN_VA_START,
|
||||
SCC_AST_EXPR_BUILTIN_VA_END,
|
||||
SCC_AST_EXPR_BUILTIN_VA_COPY,
|
||||
SCC_AST_EXPR_BUILTIN_VA_ARG,
|
||||
} scc_ast_builtin_expr_type_t;
|
||||
|
||||
/**
|
||||
* @brief 表达式节点
|
||||
*/
|
||||
@@ -328,6 +336,11 @@ struct scc_ast_expr {
|
||||
struct {
|
||||
scc_ast_type_t *type;
|
||||
} lvalue;
|
||||
// 内置表达式
|
||||
struct {
|
||||
scc_ast_builtin_expr_type_t type;
|
||||
scc_ast_expr_vec_t args;
|
||||
} builtin;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,19 @@ scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
|
||||
}
|
||||
}
|
||||
|
||||
// name and var_init can be null
|
||||
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_expr_t *var_init) {
|
||||
Assert(decl != 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;
|
||||
}
|
||||
|
||||
// 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,
|
||||
@@ -212,7 +225,7 @@ static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
|
||||
Assert(stmt != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.type = SCC_AST_STMT_DEFAULT;
|
||||
stmt->case_stmt.stmt = body;
|
||||
stmt->default_stmt.stmt = body;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt) {
|
||||
@@ -351,22 +364,26 @@ static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
|
||||
expr->cast.expr = operand;
|
||||
}
|
||||
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type) {
|
||||
Assert(expr != null && type != null);
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr) {
|
||||
Assert(expr != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.type = SCC_AST_EXPR_SIZE_OF;
|
||||
expr->attr_of.type = type;
|
||||
expr->attr_of.expr = null;
|
||||
expr->attr_of.expr = target_expr;
|
||||
}
|
||||
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type) {
|
||||
Assert(expr != null && type != null);
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr) {
|
||||
Assert(expr != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.type = SCC_AST_EXPR_SIZE_OF;
|
||||
expr->attr_of.type = type;
|
||||
expr->attr_of.expr = null;
|
||||
expr->attr_of.expr = target_expr;
|
||||
}
|
||||
|
||||
// lhs_exprs and rhs_exprs can be null
|
||||
|
||||
@@ -484,6 +484,10 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_BUILTIN:
|
||||
// PRINT_QUOTED_VALUE(ctx, scc_ast_builtin_type_name(expr->builtin));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -555,6 +559,7 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
|
||||
PRINT_VALUE(ctx, " %s", stmt->label_stmt.label);
|
||||
}
|
||||
end_node_dump(ctx);
|
||||
dump_child_node((scc_ast_node_t *)stmt->label_stmt.stmt, ctx, true);
|
||||
break;
|
||||
case SCC_AST_STMT_COMPOUND:
|
||||
end_node_dump(ctx);
|
||||
|
||||
@@ -84,7 +84,6 @@ typedef enum scc_cstd {
|
||||
|
||||
#define SCC_CTOK_TABLE \
|
||||
X(unknown , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_UNKNOWN ) \
|
||||
X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED ) \
|
||||
X(EOF , SCC_TOK_SUBTYPE_EOF, SCC_TOK_EOF ) \
|
||||
X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \
|
||||
X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \
|
||||
@@ -160,6 +159,12 @@ typedef enum scc_tok_type {
|
||||
#define X(name, subtype, tok, std) tok,
|
||||
SCC_CKEYWORD_TABLE
|
||||
#undef X
|
||||
|
||||
// FIXME hack one bit for disabled or other method
|
||||
#define X(str, subtype, tok) tok,
|
||||
X(sum , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_SUM )
|
||||
X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED )
|
||||
#undef X
|
||||
} scc_tok_type_t;
|
||||
/* clang-format on */
|
||||
|
||||
|
||||
@@ -195,8 +195,24 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (maybe_float)
|
||||
if (maybe_float) {
|
||||
token->type = SCC_TOK_FLOAT_LITERAL;
|
||||
} else {
|
||||
// FIXME 0U 0UL 0ULL 0L 0LL
|
||||
while (1) {
|
||||
if (!peek_char(lexer, &cur)) {
|
||||
break;
|
||||
}
|
||||
ch = cur.character;
|
||||
if (ch == 'U' || ch == 'u' || ch == 'L' || ch == 'l') {
|
||||
next_char(lexer, &lex, &cur);
|
||||
// 带后缀的整数字面量
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ch == '\'') {
|
||||
// 字符字面量
|
||||
token->type = SCC_TOK_CHAR_LITERAL;
|
||||
|
||||
@@ -75,8 +75,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser);
|
||||
* @param parser 解析器实例
|
||||
* @return 类型 AST 节点
|
||||
*/
|
||||
scc_ast_node_t *_scc_parse_type(scc_parser_t *parser);
|
||||
|
||||
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser);
|
||||
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser);
|
||||
|
||||
static inline void scc_parse_decl_sema(scc_parser_t *parser,
|
||||
|
||||
@@ -174,6 +174,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
. identifier
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_lexer_tok_t tok = {0};
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_expr_t *init = null;
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
||||
@@ -191,22 +192,31 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_vec_init(rhs_exprs);
|
||||
scc_ast_expr_t *lhs = null;
|
||||
scc_ast_expr_t *rhs = null;
|
||||
|
||||
scc_ast_expr_t *ptr = base;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_DOT) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_member_init(lhs, base,
|
||||
scc_cstring_as_cstr(&tok_ptr->lexeme));
|
||||
|
||||
scc_ast_expr_member_init(lhs, ptr,
|
||||
scc_cstring_as_cstr(&tok.lexeme));
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
Assert(rhs != null);
|
||||
if (rhs == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected initializer");
|
||||
Panic();
|
||||
}
|
||||
scc_vec_push(lhs_exprs, lhs);
|
||||
scc_vec_push(rhs_exprs, rhs);
|
||||
ptr = base;
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected 'identifier' after '.'");
|
||||
@@ -220,16 +230,21 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_array_subscript_init(lhs, base, idx);
|
||||
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
Assert(rhs != null);
|
||||
scc_vec_push(lhs_exprs, lhs);
|
||||
scc_vec_push(rhs_exprs, rhs);
|
||||
ptr = base;
|
||||
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
continue;
|
||||
} else {
|
||||
// FIXME
|
||||
@@ -243,31 +258,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
scc_ast_node_t *type_or_decl = _scc_parse_type(parser);
|
||||
scc_ast_decl_t *decl = null;
|
||||
if (type_or_decl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
|
||||
scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
|
||||
if (type->base.type == SCC_AST_TYPE_STRUCT ||
|
||||
type->base.type == SCC_AST_TYPE_UNION) {
|
||||
Assert(type->record.decl != null);
|
||||
decl = type->record.decl;
|
||||
scc_free(type_or_decl); // FIXME
|
||||
} else if (type->base.type == SCC_AST_TYPE_ENUM) {
|
||||
Assert(type->enumeration.decl != null);
|
||||
decl = type->enumeration.decl;
|
||||
scc_free(type_or_decl); // FIXME
|
||||
} else {
|
||||
LOG_WARN("declaration dose not declare anything");
|
||||
return null;
|
||||
}
|
||||
} else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) {
|
||||
decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
|
||||
scc_ast_decl_t *decl = scc_parse_declarator(parser);
|
||||
if (decl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -294,6 +286,8 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
Assert(decl->func.body != null);
|
||||
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ';' or '=' or '{'");
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
@@ -480,9 +480,11 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
// 可以嵌套)
|
||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||
if (!operand) {
|
||||
// 释放 type
|
||||
// TODO: 需要 scc_ast_type_drop(type);
|
||||
return null;
|
||||
// FIXME postfix-expression
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
operand = scc_parse_initializer(parser, expr);
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
@@ -505,10 +507,25 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
|
||||
// 一元表达式
|
||||
static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
/*
|
||||
(6.5.3)
|
||||
unary-expression:
|
||||
postfix-expression
|
||||
++ unary-expression
|
||||
-- unary-expression
|
||||
unary-operator cast-expression
|
||||
sizeof unary-expression
|
||||
sizeof ( type-name )
|
||||
(6.5.3)
|
||||
unary-operator: one of
|
||||
& * + - ~ !
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return null;
|
||||
|
||||
scc_lexer_tok_t tok = {0};
|
||||
|
||||
// 处理一元运算符
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_ADD_ADD: // ++x
|
||||
@@ -527,7 +544,14 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
|
||||
// 一元运算符右结合,递归调用 parse_unary_expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
|
||||
scc_ast_expr_t *operand = null;
|
||||
if (tok_ptr->type == SCC_TOK_ADD_ADD ||
|
||||
tok_ptr->type == SCC_TOK_SUB_SUB) {
|
||||
operand = parse_unary_expression(parser);
|
||||
} else {
|
||||
operand = parse_cast_expression(parser);
|
||||
}
|
||||
if (!operand) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
@@ -561,34 +585,35 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = null;
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
|
||||
// 尝试解析 sizeof(type-name)
|
||||
if (next->type == SCC_TOK_L_PAREN) {
|
||||
scc_parser_store(parser);
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||
if (type) {
|
||||
// 消耗 ')'
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"expected ')' after type-name in sizeof expression");
|
||||
}
|
||||
scc_ast_expr_sizeof_init(null, type);
|
||||
return expr;
|
||||
} else {
|
||||
TODO();
|
||||
scc_parser_next(parser);
|
||||
scc_ast_type_t *type_name = scc_parse_type_name(parser);
|
||||
if (type_name == null) {
|
||||
scc_parser_restore(parser);
|
||||
goto next;
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
// 消耗 ')'
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"expected ')' after type-name in sizeof expression");
|
||||
}
|
||||
|
||||
Assert(type_name != null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null);
|
||||
return expr;
|
||||
}
|
||||
next:
|
||||
// 尝试解析 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (operand != null) {
|
||||
scc_ast_expr_sizeof_init(expr, null, operand);
|
||||
return expr;
|
||||
}
|
||||
|
||||
// 否则作为 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (!operand) {
|
||||
scc_free(expr);
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
} else {
|
||||
scc_ast_expr_sizeof_init(operand, null);
|
||||
}
|
||||
// 否则作为 sizeof(type-name)
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -612,12 +637,10 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '{");
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
return scc_parse_initializer(parser, expr);
|
||||
left = scc_parse_initializer(parser, expr);
|
||||
return left;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@@ -736,6 +759,14 @@ done:
|
||||
|
||||
// 基本表达式
|
||||
static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
/*
|
||||
(6.5.1)
|
||||
primary-expression:
|
||||
identifier
|
||||
constant
|
||||
string-literal
|
||||
( expression )
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return null;
|
||||
@@ -779,73 +810,41 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_STRING_LITERAL: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
scc_cstring_t string = scc_cstring_create();
|
||||
scc_lexer_tok_t tok;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
break;
|
||||
}
|
||||
if (tok_ptr->type != SCC_TOK_STRING_LITERAL) {
|
||||
break;
|
||||
}
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_cstring_t tmp = scc_cstring_move(&tok.lexeme);
|
||||
scc_lexer_tok_drop(&tok);
|
||||
scc_cstring_append(&string, &tmp);
|
||||
}
|
||||
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
|
||||
true);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
return parse_paren_expression(parser);
|
||||
scc_parser_next_consume(parser, null);
|
||||
expr = scc_parse_expression(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ')' after expression");
|
||||
}
|
||||
return expr;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理括号表达式、类型转换、复合字面量
|
||||
static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) {
|
||||
// 保存位置以便回退
|
||||
scc_parser_store(parser);
|
||||
|
||||
// 尝试解析类型名
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||
if (type) {
|
||||
// 如果成功,下一个应该是 ')'
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
// 是类型转换,解析后面的 cast-expression
|
||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||
if (!operand) {
|
||||
// 释放 type
|
||||
// TODO: scc_ast_type_drop(type);
|
||||
return null;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_cast_init(expr, type, operand);
|
||||
return expr;
|
||||
} else {
|
||||
// 不是类型转换,回退并释放 type
|
||||
scc_parser_restore(parser);
|
||||
// TODO: scc_ast_type_drop(type);
|
||||
}
|
||||
} else {
|
||||
scc_parser_restore(parser);
|
||||
}
|
||||
|
||||
// 否则作为括号表达式
|
||||
scc_lexer_tok_t lp;
|
||||
if (!scc_parser_next_consume(parser, &lp) || lp.type != SCC_TOK_L_PAREN) {
|
||||
return null;
|
||||
}
|
||||
scc_lexer_tok_drop(&lp);
|
||||
|
||||
scc_ast_expr_t *inner = scc_parse_expression(parser);
|
||||
if (!inner) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ')' after expression");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
return inner;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
||||
if (!left)
|
||||
|
||||
@@ -80,7 +80,8 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
return null;
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected identifier before like `identifier : statement` .");
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
@@ -364,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
scc_parser_reset(parser);
|
||||
break;
|
||||
}
|
||||
scc_parser_reset(parser);
|
||||
stmt = parse_label_statement(parser);
|
||||
goto RETURN;
|
||||
case SCC_TOK_CASE: {
|
||||
|
||||
@@ -159,6 +159,21 @@ EXAMPLE The constructions
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
static scc_ast_type_t *parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
static scc_ast_type_t *
|
||||
parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
|
||||
static inline scc_ast_type_t *ast_type_alloc() {
|
||||
scc_ast_type_t *ast_type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
ast_type->base.type = SCC_AST_UNKNOWN;
|
||||
@@ -398,9 +413,8 @@ typedef struct {
|
||||
static cbool check_type_combinations(scc_parser_t *parser,
|
||||
type_spec_info_t *info) {
|
||||
// 基本类型不能同时出现多个(void, char, int, float, double, bool 互斥)
|
||||
int basic_count = info->is_void + info->is_char + info->is_short +
|
||||
info->is_int + info->is_float + info->is_double +
|
||||
info->is_bool;
|
||||
int basic_count = info->is_void + info->is_char + info->is_int +
|
||||
info->is_float + info->is_double + info->is_bool;
|
||||
if (basic_count > 1) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Multiple basic type specifiers");
|
||||
@@ -574,11 +588,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
break;
|
||||
}
|
||||
|
||||
scc_ast_node_t *node = _scc_parse_type(parser);
|
||||
scc_ast_decl_t *decl = null;
|
||||
if (node != null) {
|
||||
decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
}
|
||||
decl = scc_parse_declarator(parser);
|
||||
if (decl != null) {
|
||||
scc_vec_push(member, decl);
|
||||
continue;
|
||||
@@ -606,6 +616,21 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
scc_ast_decl_union_init(decl, name, &member);
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected name in struct/union specifier");
|
||||
// FIXME memory leak
|
||||
return null;
|
||||
}
|
||||
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
if (type_kind == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, name, null);
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, name, null);
|
||||
}
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
@@ -678,6 +703,16 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, name, &member);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected name in enum specifier");
|
||||
// FIXME memory leak
|
||||
return null;
|
||||
}
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, name, null);
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
@@ -818,21 +853,6 @@ duplicate_error:
|
||||
return null;
|
||||
}
|
||||
|
||||
static scc_ast_type_t *parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident);
|
||||
static scc_ast_type_t *
|
||||
parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
static scc_ast_type_t *
|
||||
parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr);
|
||||
|
||||
static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
scc_ast_type_t *pointee,
|
||||
scc_ast_type_t **delay_pointee_ptr) {
|
||||
@@ -875,22 +895,15 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
scc_ast_decl_t *param = null;
|
||||
while (1) {
|
||||
// FIXME
|
||||
scc_ast_node_t *node = _scc_parse_type(parser);
|
||||
if (node == null) {
|
||||
scc_ast_decl_t *decl = scc_parse_declarator(parser);
|
||||
if (decl == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SCC_AST_IS_A(scc_ast_decl_t, node)) {
|
||||
param = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
// TODO Check validation
|
||||
Assert(param->base.type = SCC_AST_DECL_VAR);
|
||||
param->base.type = SCC_AST_DECL_PARAM;
|
||||
} else if (SCC_AST_IS_A(scc_ast_type_t, node)) {
|
||||
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(param != null);
|
||||
scc_ast_decl_param_init(
|
||||
param, SCC_AST_CAST_TO(scc_ast_type_t, node), null);
|
||||
}
|
||||
// TODO Check validation
|
||||
param = SCC_AST_CAST_TO(scc_ast_decl_t, decl);
|
||||
Assert(param->base.type = SCC_AST_DECL_VAR);
|
||||
param->base.type = SCC_AST_DECL_PARAM;
|
||||
|
||||
scc_vec_push(*params, param);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
@@ -1129,7 +1142,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
}
|
||||
}
|
||||
|
||||
scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
|
||||
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser) {
|
||||
if (!scc_parse_is_decl_specifier_start(parser)) {
|
||||
return null;
|
||||
}
|
||||
@@ -1177,7 +1190,37 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
|
||||
}
|
||||
}
|
||||
|
||||
return decl != null ? &decl->base : &type->base;
|
||||
scc_ast_node_t *type_or_decl = decl != null ? &decl->base : &type->base;
|
||||
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
|
||||
scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
|
||||
if (type->base.type == SCC_AST_TYPE_STRUCT ||
|
||||
type->base.type == SCC_AST_TYPE_UNION) {
|
||||
if (type->record.decl == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"record don't have a decl");
|
||||
Panic();
|
||||
}
|
||||
decl = type->record.decl;
|
||||
scc_free(type_or_decl); // FIXME
|
||||
} else if (type->base.type == SCC_AST_TYPE_ENUM) {
|
||||
if (type->enumeration.decl == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"enum don't have a decl");
|
||||
Panic();
|
||||
}
|
||||
decl = type->enumeration.decl;
|
||||
scc_free(type_or_decl); // FIXME
|
||||
} else {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null);
|
||||
}
|
||||
} else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) {
|
||||
decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "invalid declaration");
|
||||
return null;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <assert.h>
|
||||
#include <scc_lexer.h>
|
||||
#include <scc_parser.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utest/acutest.h>
|
||||
|
||||
@@ -56,8 +57,9 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
|
||||
char *buffer = _buffer;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
scc_vsnprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer) - 1,
|
||||
fmt, args);
|
||||
int res = scc_vsnprintf(buffer + strlen(buffer),
|
||||
BUFFER_SIZE - strlen(buffer) - 1, fmt, args);
|
||||
Assert(res > 0);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -589,6 +591,153 @@ static void test_parser_unit(void) {
|
||||
SCC_CHECK_AST(&expr.base,
|
||||
"(void){.data = ((void *)0), .size = 0, .cap = 0}",
|
||||
scc_parse_expression);
|
||||
|
||||
scc_ast_stmt_t stmt;
|
||||
scc_ast_stmt_return_init(&stmt, &expr);
|
||||
SCC_CHECK_AST(&stmt.base,
|
||||
"return (void){.data = (void *)0, .size = 0, .cap = 0};",
|
||||
scc_parse_statement);
|
||||
|
||||
scc_ast_expr_t lhs4;
|
||||
scc_ast_expr_t lhs5;
|
||||
scc_ast_expr_member_init(&lhs4, &lvalue, "a");
|
||||
scc_ast_expr_member_init(&lhs5, &lhs4, "b");
|
||||
scc_ast_expr_t lhs6;
|
||||
scc_ast_expr_t lhs7;
|
||||
scc_ast_expr_member_init(&lhs6, &lvalue, "c");
|
||||
scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0);
|
||||
|
||||
scc_ast_expr_t *lhs_array_hard[] = {&lhs5, &lhs7};
|
||||
scc_vec_unsafe_from_array(lhs_exprs, lhs_array_hard);
|
||||
scc_ast_expr_t *rhs_array_hard[] = {&rhs2, &rhs3};
|
||||
scc_vec_unsafe_from_array(rhs_exprs, rhs_array_hard);
|
||||
scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs);
|
||||
SCC_CHECK_AST(&expr.base, "(void){.a.b = 0, .c[0] = 0}",
|
||||
scc_parse_expression);
|
||||
}
|
||||
|
||||
{
|
||||
// 测试 struct S; 仅标记声明
|
||||
{
|
||||
scc_ast_decl_t struct_decl;
|
||||
scc_ast_decl_vec_t empty_members;
|
||||
scc_vec_init(empty_members);
|
||||
scc_ast_decl_struct_init(&struct_decl, "S", &empty_members);
|
||||
SCC_CHECK_AST(&struct_decl.base, "struct S;",
|
||||
scc_parse_declaration);
|
||||
}
|
||||
|
||||
// 测试 union U; 仅标记声明
|
||||
{
|
||||
scc_ast_decl_t union_decl;
|
||||
scc_ast_decl_vec_t empty_members;
|
||||
scc_vec_init(empty_members);
|
||||
scc_ast_decl_union_init(&union_decl, "U", &empty_members);
|
||||
SCC_CHECK_AST(&union_decl.base, "union U;", scc_parse_declaration);
|
||||
}
|
||||
|
||||
// 测试 enum E; 仅标记声明
|
||||
{
|
||||
scc_ast_decl_t enum_decl;
|
||||
scc_ast_expr_vec_t empty_enumerators;
|
||||
scc_vec_init(empty_enumerators);
|
||||
scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators);
|
||||
SCC_CHECK_AST(&enum_decl.base, "enum E;", scc_parse_declaration);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
scc_ast_stmt_t continue_stmt;
|
||||
scc_ast_stmt_continue_init(&continue_stmt);
|
||||
scc_ast_stmt_t stmt;
|
||||
scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt);
|
||||
SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement);
|
||||
|
||||
scc_ast_expr_t str;
|
||||
scc_ast_expr_literal_string_init(&str, "\"ab\"", false);
|
||||
SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression);
|
||||
}
|
||||
|
||||
{
|
||||
// 测试 int a = *(int*)b;
|
||||
{
|
||||
// 构造类型 int*
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(
|
||||
&ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
|
||||
// 标识符 b
|
||||
scc_ast_expr_t b_expr;
|
||||
scc_ast_expr_identifier_init(&b_expr, "b");
|
||||
|
||||
// 类型转换 (int*)b
|
||||
scc_ast_expr_t cast_expr;
|
||||
scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr);
|
||||
|
||||
// 解引用 *(int*)b
|
||||
scc_ast_expr_t deref_expr;
|
||||
scc_ast_expr_unary_init(&deref_expr, SCC_AST_OP_INDIRECTION,
|
||||
&cast_expr);
|
||||
|
||||
// 声明 int a = *(int*)b;
|
||||
scc_ast_decl_t decl;
|
||||
scc_ast_decl_val_init(&decl,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
"a", &deref_expr);
|
||||
|
||||
SCC_CHECK_AST(&decl.base, "int a = *(int*)b;",
|
||||
scc_parse_declaration);
|
||||
}
|
||||
|
||||
// // 测试 int a, b;
|
||||
// {
|
||||
// scc_ast_decl_t decl_a, decl_b;
|
||||
// scc_ast_decl_val_init(&decl_a,
|
||||
// (scc_ast_type_t
|
||||
// *)&scc_ast_builtin_type_int, "a", null);
|
||||
// scc_ast_decl_val_init(&decl_b,
|
||||
// (scc_ast_type_t
|
||||
// *)&scc_ast_builtin_type_int, "b", null);
|
||||
|
||||
// scc_ast_decl_vec_t decl_vec;
|
||||
// scc_vec_init(decl_vec);
|
||||
// scc_vec_push(decl_vec, &decl_a);
|
||||
// scc_vec_push(decl_vec, &decl_b);
|
||||
|
||||
// scc_ast_decl_t decl_list;
|
||||
// scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数
|
||||
|
||||
// SCC_CHECK_AST(&decl_list.base, "int a, b;",
|
||||
// scc_parse_declaration);
|
||||
// }
|
||||
|
||||
// // 测试 int a = 1, b = 2;
|
||||
// {
|
||||
// scc_ast_expr_t lit1, lit2;
|
||||
// scc_ast_expr_literal_int_init(&lit1, "1", false);
|
||||
// scc_ast_expr_literal_int_init(&lit2, "2", false);
|
||||
|
||||
// scc_ast_decl_t decl_a, decl_b;
|
||||
// scc_ast_decl_val_init(&decl_a,
|
||||
// (scc_ast_type_t
|
||||
// *)&scc_ast_builtin_type_int, "a", &lit1);
|
||||
// scc_ast_decl_val_init(&decl_b,
|
||||
// (scc_ast_type_t
|
||||
// *)&scc_ast_builtin_type_int, "b", &lit2);
|
||||
|
||||
// scc_ast_decl_vec_t decl_vec;
|
||||
// scc_vec_init(decl_vec);
|
||||
// scc_vec_push(decl_vec, &decl_a);
|
||||
// scc_vec_push(decl_vec, &decl_b);
|
||||
|
||||
// scc_ast_decl_t decl_list;
|
||||
// scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数
|
||||
|
||||
// SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;",
|
||||
// scc_parse_declaration);
|
||||
// }
|
||||
"__scc_builtin_va_arg(ag, int)";
|
||||
"__scc_builtin_va_arg(ag, long long)";
|
||||
}
|
||||
|
||||
{
|
||||
@@ -775,10 +924,16 @@ static void test_parser_expression(void) {
|
||||
SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression);
|
||||
|
||||
// sizeof 表达式
|
||||
// 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);
|
||||
scc_ast_expr_t sizeof_x_expr;
|
||||
scc_ast_expr_sizeof_init(&sizeof_x_expr, null, &x);
|
||||
SCC_CHECK_AST(&sizeof_x_expr.base, "sizeof(x)", scc_parse_expression);
|
||||
|
||||
scc_ast_expr_t sizeof_int_expr;
|
||||
scc_ast_expr_sizeof_init(&sizeof_int_expr,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
null);
|
||||
SCC_CHECK_AST(&sizeof_int_expr.base, "sizeof(int)",
|
||||
scc_parse_expression);
|
||||
}
|
||||
|
||||
// 4. 类型转换(示例: (int)x )
|
||||
@@ -935,7 +1090,7 @@ static void test_parser_type(void) {
|
||||
// 1. int
|
||||
{
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 2. int *
|
||||
@@ -943,7 +1098,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(
|
||||
&ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 3. int *[3]
|
||||
@@ -957,7 +1112,7 @@ static void test_parser_type(void) {
|
||||
|
||||
scc_ast_type_t array_of_ptr;
|
||||
scc_ast_type_array_init(&array_of_ptr, &ptr_to_int, &size_3);
|
||||
SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 4. int (*)[3]
|
||||
@@ -972,7 +1127,8 @@ static void test_parser_type(void) {
|
||||
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_int);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]",
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 5. int (*)[*]
|
||||
@@ -985,7 +1141,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_array_var;
|
||||
scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var);
|
||||
SCC_CHECK_AST(&ptr_to_array_var.base, "int (*)[*]",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 6. int *()
|
||||
@@ -998,7 +1154,7 @@ static void test_parser_type(void) {
|
||||
// 函数类型,返回 int*,无参数
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &ptr_to_int, null);
|
||||
SCC_CHECK_AST(&func_type.base, "int *()", _scc_parse_type);
|
||||
SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 7. int (*)(void)
|
||||
@@ -1017,7 +1173,8 @@ static void test_parser_type(void) {
|
||||
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_void);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)",
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 8. int (*const [])(unsigned int, ...)
|
||||
@@ -1058,51 +1215,59 @@ static void test_parser_type(void) {
|
||||
|
||||
SCC_CHECK_AST(&array_of_ptr.base,
|
||||
"int (*const [])(unsigned int, ...)",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 基本内置类型及组合
|
||||
{
|
||||
// int
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int",
|
||||
_scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_int.base, "int",
|
||||
scc_parse_type_name);
|
||||
|
||||
// char
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_char, "char",
|
||||
_scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_char.base, "char",
|
||||
scc_parse_type_name);
|
||||
|
||||
// long long
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_long,
|
||||
"long long", _scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long",
|
||||
scc_parse_type_name);
|
||||
|
||||
// long long
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long int",
|
||||
scc_parse_type_name);
|
||||
|
||||
// short
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_short.base, "short int",
|
||||
scc_parse_type_name);
|
||||
|
||||
// unsigned int
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_unsigned_int,
|
||||
"unsigned int", _scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_unsigned_int.base, "unsigned int",
|
||||
scc_parse_type_name);
|
||||
|
||||
// float
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_float, "float",
|
||||
_scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_float.base, "float",
|
||||
scc_parse_type_name);
|
||||
|
||||
// double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_double, "double",
|
||||
_scc_parse_type);
|
||||
SCC_CHECK_AST(&scc_ast_builtin_type_double.base, "double",
|
||||
scc_parse_type_name);
|
||||
|
||||
// void
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_void, "void",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// bool
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_bool, "bool",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// long double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_double,
|
||||
"long double", _scc_parse_type);
|
||||
"long double", scc_parse_type_name);
|
||||
|
||||
// _Complex double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double,
|
||||
"double complex", _scc_parse_type);
|
||||
"double complex", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 2. 带类型限定符的基本类型 (const, volatile)
|
||||
@@ -1110,20 +1275,20 @@ static void test_parser_type(void) {
|
||||
// const int
|
||||
scc_ast_type_t const_int = scc_ast_builtin_type_int;
|
||||
const_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_int.base, "const int", _scc_parse_type);
|
||||
SCC_CHECK_AST(&const_int.base, "const int", scc_parse_type_name);
|
||||
|
||||
// volatile unsigned long
|
||||
scc_ast_type_t volatile_ulong = scc_ast_builtin_type_unsigned_long;
|
||||
volatile_ulong.quals.is_volatile = true;
|
||||
SCC_CHECK_AST(&volatile_ulong.base, "volatile unsigned long",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// const volatile char
|
||||
scc_ast_type_t const_volatile_char = scc_ast_builtin_type_char;
|
||||
const_volatile_char.quals.is_const = true;
|
||||
const_volatile_char.quals.is_volatile = true;
|
||||
SCC_CHECK_AST(&const_volatile_char.base, "const volatile char",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 3. 指针类型
|
||||
@@ -1132,33 +1297,35 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name);
|
||||
|
||||
// int **
|
||||
scc_ast_type_t ptr_to_ptr_to_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_ptr_to_int, &ptr_to_int);
|
||||
SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", scc_parse_type_name);
|
||||
|
||||
// int * const (const pointer to int)
|
||||
scc_ast_type_t const_ptr_to_int;
|
||||
scc_ast_type_pointer_init(&const_ptr_to_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
const_ptr_to_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", _scc_parse_type);
|
||||
SCC_CHECK_AST(&const_ptr_to_int.base, "int * const",
|
||||
scc_parse_type_name);
|
||||
|
||||
// const int * (pointer to const int)
|
||||
scc_ast_type_t const_int_type = scc_ast_builtin_type_int;
|
||||
const_int_type.quals.is_const = true;
|
||||
scc_ast_type_t ptr_to_const_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_const_int, &const_int_type);
|
||||
SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_const_int.base, "const int *",
|
||||
scc_parse_type_name);
|
||||
|
||||
// const int * const (const pointer to const int)
|
||||
scc_ast_type_t const_ptr_to_const_int;
|
||||
scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int_type);
|
||||
const_ptr_to_const_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// volatile int * restrict
|
||||
scc_ast_type_t volatile_int = scc_ast_builtin_type_int;
|
||||
@@ -1167,7 +1334,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int);
|
||||
restrict_ptr_to_volatile_int.quals.is_restrict = true;
|
||||
SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base,
|
||||
"volatile int * restrict", _scc_parse_type);
|
||||
"volatile int * restrict", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 4. 数组类型
|
||||
@@ -1179,14 +1346,15 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_array_init(&array_of_5_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&size_5);
|
||||
SCC_CHECK_AST(&array_of_5_int.base, "int [5]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&array_of_5_int.base, "int [5]", scc_parse_type_name);
|
||||
|
||||
// int [] (不完整类型)
|
||||
scc_ast_type_t array_of_int_unknown;
|
||||
scc_ast_type_array_init(&array_of_int_unknown,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
null);
|
||||
SCC_CHECK_AST(&array_of_int_unknown.base, "int []", _scc_parse_type);
|
||||
SCC_CHECK_AST(&array_of_int_unknown.base, "int []",
|
||||
scc_parse_type_name);
|
||||
|
||||
// // int [*] (变长数组原型中的不定长数组)
|
||||
// FIXME
|
||||
@@ -1208,7 +1376,7 @@ static void test_parser_type(void) {
|
||||
&inner_array, (scc_ast_type_t *)&scc_ast_builtin_type_int, &size_3);
|
||||
scc_ast_type_t outer_array;
|
||||
scc_ast_type_array_init(&outer_array, &inner_array, &size_5);
|
||||
SCC_CHECK_AST(&outer_array.base, "int [5][3]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&outer_array.base, "int [5][3]", scc_parse_type_name);
|
||||
|
||||
// int (*)[5] (指向数组的指针) 已在前面测试,这里重复以保持完整性
|
||||
scc_ast_type_t array_of_5_int2;
|
||||
@@ -1217,7 +1385,7 @@ static void test_parser_type(void) {
|
||||
&size_5);
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int2);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", scc_parse_type_name);
|
||||
|
||||
// int *[5] (指针数组)
|
||||
scc_ast_type_t ptr_to_int2;
|
||||
@@ -1225,14 +1393,14 @@ static void test_parser_type(void) {
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
scc_ast_type_t array_of_5_ptr;
|
||||
scc_ast_type_array_init(&array_of_5_ptr, &ptr_to_int2, &size_5);
|
||||
SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", scc_parse_type_name);
|
||||
|
||||
// const int [5] (数组元素为const int)
|
||||
scc_ast_type_t const_int2 = scc_ast_builtin_type_int;
|
||||
const_int2.quals.is_const = true;
|
||||
scc_ast_type_t const_array;
|
||||
scc_ast_type_array_init(&const_array, &const_int2, &size_5);
|
||||
SCC_CHECK_AST(&const_array.base, "const int [5]", _scc_parse_type);
|
||||
SCC_CHECK_AST(&const_array.base, "const int [5]", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 5. 函数类型
|
||||
@@ -1247,7 +1415,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_function_init(&func_void,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&func_params);
|
||||
SCC_CHECK_AST(&func_void.base, "int (void)", _scc_parse_type);
|
||||
SCC_CHECK_AST(&func_void.base, "int (void)", scc_parse_type_name);
|
||||
|
||||
// // int () (无参数声明,非原型)
|
||||
// //
|
||||
@@ -1271,7 +1439,7 @@ static void test_parser_type(void) {
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms);
|
||||
SCC_CHECK_AST(&func_with_params.base, "int (int, float)",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// int (int, ...) (可变参数)
|
||||
scc_ast_decl_t param_int, param_var;
|
||||
@@ -1289,7 +1457,8 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_function_init(&func_varargs,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms_var);
|
||||
SCC_CHECK_AST(&func_varargs.base, "int (int, ...)", _scc_parse_type);
|
||||
SCC_CHECK_AST(&func_varargs.base, "int (int, ...)",
|
||||
scc_parse_type_name);
|
||||
|
||||
// int (*)(int) (函数指针)
|
||||
scc_ast_decl_t param;
|
||||
@@ -1304,7 +1473,7 @@ static void test_parser_type(void) {
|
||||
&func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, ¶ms2);
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", _scc_parse_type);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 6. 函数指针和复杂声明符
|
||||
@@ -1340,7 +1509,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
|
||||
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// int (*(*)[5])(void) (指向数组的指针,数组元素为函数指针)
|
||||
// 1) 函数类型:返回 int,无参数
|
||||
@@ -1363,7 +1532,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_array_of_ptr;
|
||||
scc_ast_type_pointer_init(&ptr_to_array_of_ptr, &array_of_ptr_to_func);
|
||||
SCC_CHECK_AST(&ptr_to_array_of_ptr.base, "int (*(*)[5])(void)",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 7. 结构体/联合/枚举类型(标记和定义)
|
||||
@@ -1372,7 +1541,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t struct_tag;
|
||||
scc_ast_type_struct_init(&struct_tag, "S",
|
||||
null); // name="S", members=null
|
||||
SCC_CHECK_AST(&struct_tag.base, "struct S", _scc_parse_type);
|
||||
SCC_CHECK_AST(&struct_tag.base, "struct S", scc_parse_type_name);
|
||||
|
||||
// struct { int x; } (匿名结构体定义)
|
||||
scc_ast_decl_t field;
|
||||
@@ -1386,18 +1555,19 @@ static void test_parser_type(void) {
|
||||
scc_ast_decl_struct_init(&struct_def, null, &fields);
|
||||
scc_ast_type_t struct_type;
|
||||
scc_ast_type_struct_init(&struct_type, null, &struct_def);
|
||||
SCC_CHECK_AST(&struct_type.base, "struct { int x; }", _scc_parse_type);
|
||||
SCC_CHECK_AST(&struct_type.base, "struct { int x; }",
|
||||
scc_parse_type_name);
|
||||
scc_vec_init(fields);
|
||||
scc_vec_push(fields, &field);
|
||||
scc_ast_decl_struct_init(&struct_def, "A", &fields);
|
||||
scc_ast_type_struct_init(&struct_type, "A", &struct_def);
|
||||
SCC_CHECK_AST(&struct_type.base, "struct A { int x; }",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// union U (不完整类型)
|
||||
scc_ast_type_t union_tag;
|
||||
scc_ast_type_union_init(&union_tag, "U", null);
|
||||
SCC_CHECK_AST(&union_tag.base, "union U", _scc_parse_type);
|
||||
SCC_CHECK_AST(&union_tag.base, "union U", scc_parse_type_name);
|
||||
|
||||
// union { int a; float b; } (匿名联合定义)
|
||||
scc_ast_decl_t field_a, field_b;
|
||||
@@ -1415,16 +1585,16 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t union_type;
|
||||
scc_ast_type_union_init(&union_type, null, &union_def);
|
||||
SCC_CHECK_AST(&union_type.base, "union { int a; float b; }",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
scc_ast_decl_union_init(&union_def, "Union", &fields_union);
|
||||
scc_ast_type_union_init(&union_type, "Union", &union_def);
|
||||
SCC_CHECK_AST(&union_type.base, "union Union { int a; float b; }",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// enum E (不完整类型)
|
||||
scc_ast_type_t enum_tag;
|
||||
scc_ast_type_enum_init(&enum_tag, "E", null);
|
||||
SCC_CHECK_AST(&enum_tag.base, "enum E", _scc_parse_type);
|
||||
SCC_CHECK_AST(&enum_tag.base, "enum E", scc_parse_type_name);
|
||||
|
||||
// enum { RED, GREEN, BLUE } (匿名枚举定义)
|
||||
scc_ast_expr_t red, green, blue;
|
||||
@@ -1440,13 +1610,13 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t enum_type;
|
||||
scc_ast_type_enum_init(&enum_type, null, &enum_def);
|
||||
SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
scc_vec_unsafe_from_array(enumerators, array);
|
||||
scc_ast_decl_enum_init(&enum_def, "E", &enumerators);
|
||||
scc_ast_type_enum_init(&enum_type, "E", &enum_def);
|
||||
SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
|
||||
// 8. typedef 类型
|
||||
@@ -1490,7 +1660,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
|
||||
// float (*(*)(int, ...))()
|
||||
// 1) float 类型作为内部函数返回类型
|
||||
@@ -1524,7 +1694,7 @@ static void test_parser_type(void) {
|
||||
scc_ast_type_t ptr_to_outer_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_outer_func, &outer_func);
|
||||
SCC_CHECK_AST(&ptr_to_outer_func.base, "float (*(*)(int, ...))()",
|
||||
_scc_parse_type);
|
||||
scc_parse_type_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,15 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
|
||||
const scc_pproc_macro_t *macro,
|
||||
scc_lexer_tok_vec_t *tok_buffer);
|
||||
|
||||
static inline scc_lexer_tok_t scc_pproc_tok_copy(scc_pproc_expand_t *ctx,
|
||||
const scc_lexer_tok_t *src) {
|
||||
scc_lexer_tok_t dst = scc_lexer_tok_copy(src);
|
||||
if (ctx->need_keep_org_pos) {
|
||||
dst.loc = ctx->call_pos;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_vec_t *arg_tokens) {
|
||||
// WRITE BY AI
|
||||
@@ -13,8 +22,9 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_cstring_append_ch(&str, '\"'); // 左引号
|
||||
|
||||
int need_space = 0; // 是否需要插入空格
|
||||
scc_lexer_tok_t *tok = null;
|
||||
scc_vec_foreach(*arg_tokens, i) {
|
||||
scc_lexer_tok_t *tok = &scc_vec_at(*arg_tokens, i);
|
||||
tok = &scc_vec_at(*arg_tokens, i);
|
||||
if (tok->type == SCC_TOK_BLANK) {
|
||||
need_space = 1; // 标记遇到空白
|
||||
continue;
|
||||
@@ -39,8 +49,11 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_t result;
|
||||
result.type = SCC_TOK_STRING_LITERAL;
|
||||
result.lexeme = str;
|
||||
if (ctx->need_keep_org_pos)
|
||||
if (ctx->need_keep_org_pos) {
|
||||
result.loc = ctx->call_pos;
|
||||
} else {
|
||||
result.loc = tok ? tok->loc : scc_pos_create();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -88,8 +101,9 @@ RETURN:
|
||||
scc_lexer_drop_ring(ring);
|
||||
scc_lexer_drop(&lexer);
|
||||
scc_sstream_drop(&sstream);
|
||||
if (ctx->need_keep_org_pos)
|
||||
if (ctx->need_keep_org_pos) {
|
||||
result.loc = ctx->call_pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,6 +116,7 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx,
|
||||
copyed_ctx->macro_table = expand_ctx->macro_table;
|
||||
copyed_ctx->need_rescan = false;
|
||||
copyed_ctx->need_parse_defined = expand_ctx->need_parse_defined;
|
||||
copyed_ctx->need_keep_org_pos = expand_ctx->need_keep_org_pos;
|
||||
scc_vec_init(copyed_ctx->output);
|
||||
}
|
||||
|
||||
@@ -394,7 +409,7 @@ static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
|
||||
scc_lexer_tok_vec_t tok_buffer;
|
||||
@@ -403,7 +418,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
|
||||
scc_lexer_tok_vec_t raw_args;
|
||||
scc_vec_init(raw_args);
|
||||
scc_pproc_parse_macro_arguments(expand_ctx->input, &raw_args, false);
|
||||
scc_pproc_parse_macro_arguments(ctx->input, &raw_args, false);
|
||||
|
||||
// collect, fill and expand arg
|
||||
scc_pproc_macro_extened_params_t splited_params;
|
||||
@@ -414,15 +429,13 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
|
||||
scc_pproc_macro_extened_params_t expanded_params;
|
||||
scc_vec_init(expanded_params);
|
||||
expand_arguments(&expanded_params, &splited_params, expand_ctx);
|
||||
expand_arguments(&expanded_params, &splited_params, ctx);
|
||||
Assert(scc_vec_size(expanded_params) >= scc_vec_size(macro->params));
|
||||
|
||||
// replace
|
||||
scc_vec_foreach(macro->replaces, i) {
|
||||
scc_lexer_tok_t tok =
|
||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||
if (expand_ctx->need_keep_org_pos)
|
||||
tok.loc = expand_ctx->call_pos;
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||||
@@ -444,8 +457,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro);
|
||||
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
|
||||
|
||||
tok =
|
||||
stringify_argument(expand_ctx, &scc_vec_at(splited_params, j));
|
||||
tok = stringify_argument(ctx, &scc_vec_at(splited_params, j));
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
i = right_idx;
|
||||
continue;
|
||||
@@ -468,11 +480,11 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
Assert(idx < (int)scc_vec_size(splited_params));
|
||||
scc_lexer_tok_vec_t *tok_vec = &scc_vec_at(splited_params, idx);
|
||||
scc_vec_foreach(*tok_vec, j) {
|
||||
scc_vec_push(right_vec,
|
||||
scc_lexer_tok_copy(&scc_vec_at(*tok_vec, j)));
|
||||
scc_vec_push(right_vec, scc_pproc_tok_copy(
|
||||
ctx, &scc_vec_at(*tok_vec, j)));
|
||||
}
|
||||
} else {
|
||||
scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok));
|
||||
scc_vec_push(right_vec, scc_pproc_tok_copy(ctx, right_tok));
|
||||
}
|
||||
|
||||
scc_lexer_tok_t *right =
|
||||
@@ -482,12 +494,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
|
||||
"__VA_ARGS__") == 0) {
|
||||
if (scc_vec_size(right_vec) == 0) {
|
||||
concact(expand_ctx, &tok_buffer, right, true);
|
||||
concact(ctx, &tok_buffer, right, true);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
concact(expand_ctx, &tok_buffer, right, false);
|
||||
concact(ctx, &tok_buffer, right, false);
|
||||
}
|
||||
|
||||
scc_vec_foreach(right_vec, j) {
|
||||
@@ -512,7 +524,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
scc_vec_at(expanded_params, j);
|
||||
scc_lexer_tok_drop(&tok);
|
||||
scc_vec_foreach(expanded_param, k) {
|
||||
tok = scc_lexer_tok_copy(&scc_vec_at(expanded_param, k));
|
||||
tok =
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(expanded_param, k));
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
}
|
||||
continue;
|
||||
@@ -523,20 +536,18 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
expanded_params_free(&splited_params);
|
||||
expanded_params_free(&expanded_params);
|
||||
|
||||
rescan(expand_ctx, macro, &tok_buffer);
|
||||
rescan(ctx, macro, &tok_buffer);
|
||||
Assert(tok_buffer.cap == 0); // FIXME
|
||||
}
|
||||
|
||||
static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
||||
static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
scc_lexer_tok_vec_t tok_buffer;
|
||||
scc_vec_init(tok_buffer);
|
||||
|
||||
scc_vec_foreach(macro->replaces, i) {
|
||||
scc_lexer_tok_t tok =
|
||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||
if (expand_ctx->need_keep_org_pos)
|
||||
tok.loc = expand_ctx->call_pos;
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
// FIXME using function to warpper it
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
@@ -553,14 +564,14 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
||||
right = &scc_vec_at(macro->replaces, right_idx);
|
||||
}
|
||||
|
||||
concact(expand_ctx, &tok_buffer, right, false);
|
||||
concact(ctx, &tok_buffer, right, false);
|
||||
i = right_idx;
|
||||
continue;
|
||||
}
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
}
|
||||
|
||||
rescan(expand_ctx, macro, &tok_buffer);
|
||||
rescan(ctx, macro, &tok_buffer);
|
||||
}
|
||||
|
||||
static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||||
@@ -640,8 +651,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||
|
||||
if (macro == null || need_skip(expand_ctx, macro)) {
|
||||
// FIXME maybe keyword is error or don't parse c keyword or number
|
||||
// 这个地方不太清楚正确的原因
|
||||
tok.type = SCC_TOK_DISABLED;
|
||||
tok.type += SCC_TOK_DISABLED;
|
||||
scc_vec_push(expand_ctx->output, tok);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,14 @@ static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) {
|
||||
cbool ret = false;
|
||||
CONTINUE:
|
||||
ret = pproc_next(pp, tok);
|
||||
// FIXME Hack the token
|
||||
if (ret && tok->type >= SCC_TOK_DISABLED) {
|
||||
tok->type -= SCC_TOK_DISABLED;
|
||||
}
|
||||
|
||||
if (ret && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_INVALID) {
|
||||
PanicFmt("Invalid token: %s", scc_cstring_as_cstr(&tok->lexeme));
|
||||
}
|
||||
if (ret && !pp->ring_need_comment &&
|
||||
scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_COMMENT) {
|
||||
scc_lexer_tok_drop(tok);
|
||||
|
||||
@@ -34,8 +34,105 @@ static void test_define_pos(void) {
|
||||
scc_sstream_drop(&mem_stream);
|
||||
}
|
||||
|
||||
static void test_define_double_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input = "#define _OBJ 1\n#define OBJ _OBJ\nOBJ";
|
||||
ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false,
|
||||
16);
|
||||
Assert(ret == 0);
|
||||
|
||||
scc_lexer_t lexer;
|
||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream));
|
||||
|
||||
scc_pproc_t pp;
|
||||
scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true));
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true);
|
||||
scc_lexer_tok_t tok = {0};
|
||||
|
||||
scc_ring_next_consume(*tok_ring, tok, ret);
|
||||
Assert(ret == true);
|
||||
TEST_CHECK(tok.loc.line == 3 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "1") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 3, 1, "1");
|
||||
TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col,
|
||||
tok.lexeme.data);
|
||||
|
||||
scc_ring_free(*tok_ring);
|
||||
scc_pproc_drop(&pp);
|
||||
scc_lexer_drop(&lexer);
|
||||
scc_sstream_drop(&mem_stream);
|
||||
}
|
||||
|
||||
static void test_define_param_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input = "#define OBJ 1\n#define func(x) x\nfunc(OBJ)";
|
||||
ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false,
|
||||
16);
|
||||
Assert(ret == 0);
|
||||
|
||||
scc_lexer_t lexer;
|
||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream));
|
||||
|
||||
scc_pproc_t pp;
|
||||
scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true));
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true);
|
||||
scc_lexer_tok_t tok = {0};
|
||||
|
||||
scc_ring_next_consume(*tok_ring, tok, ret);
|
||||
Assert(ret == true);
|
||||
TEST_CHECK(tok.loc.line == 3 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "1") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 3, 1, "1");
|
||||
TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col,
|
||||
tok.lexeme.data);
|
||||
|
||||
scc_ring_free(*tok_ring);
|
||||
scc_pproc_drop(&pp);
|
||||
scc_lexer_drop(&lexer);
|
||||
scc_sstream_drop(&mem_stream);
|
||||
}
|
||||
|
||||
static void test_define_stringify_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input =
|
||||
"#define _STR(x) #x\n#define STR(x) _STR(x)\n#define OBJ 1\nSTR(OBJ)";
|
||||
ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false,
|
||||
16);
|
||||
Assert(ret == 0);
|
||||
|
||||
scc_lexer_t lexer;
|
||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream));
|
||||
|
||||
scc_pproc_t pp;
|
||||
scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true));
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true);
|
||||
scc_lexer_tok_t tok = {0};
|
||||
|
||||
scc_ring_next_consume(*tok_ring, tok, ret);
|
||||
Assert(ret == true);
|
||||
TEST_CHECK(tok.loc.line == 4 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "\"1\"") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 4, 1, "\"1\"");
|
||||
TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col,
|
||||
tok.lexeme.data);
|
||||
|
||||
scc_ring_free(*tok_ring);
|
||||
scc_pproc_drop(&pp);
|
||||
scc_lexer_drop(&lexer);
|
||||
scc_sstream_drop(&mem_stream);
|
||||
}
|
||||
|
||||
#define TEST_LIST_CASE(func_name) {#func_name, func_name}
|
||||
TEST_LIST = {
|
||||
TEST_LIST_CASE(test_define_pos),
|
||||
TEST_LIST_CASE(test_define_double_pos),
|
||||
TEST_LIST_CASE(test_define_param_pos),
|
||||
TEST_LIST_CASE(test_define_stringify_pos),
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -541,6 +541,8 @@ static void test_gnu_comma_variadic_deletion(void) {
|
||||
"printf(\"%d\",42)\n");
|
||||
}
|
||||
|
||||
static void test_real_case(void) {}
|
||||
|
||||
static void test_c99_docs(void) {
|
||||
TEST_CASE("6.10.3.3 The ## operator EXAMPLE");
|
||||
CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n"
|
||||
@@ -644,6 +646,8 @@ TEST_LIST = {
|
||||
TEST_LIST_CASE(test_variadic_macros),
|
||||
TEST_LIST_CASE(test_gnu_comma_variadic_deletion),
|
||||
|
||||
TEST_LIST_CASE(test_real_case),
|
||||
|
||||
TEST_LIST_CASE(test_c99_docs),
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__ // GCC, Clang
|
||||
#define __smcc_log_unreachable() (__builtin_unreachable())
|
||||
#define __scc_log_unreachable() (__builtin_unreachable())
|
||||
#elif defined _MSC_VER // MSVC
|
||||
#define __smcc_log_unreachable() (__assume(false))
|
||||
#elif defined __SCC_BUILT_IN__ // The SCC Compiler (my compiler)
|
||||
#define __smcc_log_unreachable() (__smcc_builtin_unreachable())
|
||||
#define __scc_log_unreachable() (__assume(false))
|
||||
#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler)
|
||||
#define __scc_log_unreachable() (__scc_builtin_unreachable())
|
||||
#else
|
||||
#define __smcc_log_unreachable()
|
||||
#define __scc_log_unreachable() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef log_vsnprintf
|
||||
@@ -155,7 +155,7 @@ void log_set_handler(logger_t *logger, log_handler handler);
|
||||
((void)((cond) || \
|
||||
(__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
|
||||
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
|
||||
log_exit(1), __smcc_log_unreachable(), 0)))
|
||||
log_exit(1), __scc_log_unreachable(), 0)))
|
||||
|
||||
/// @name 断言工具宏
|
||||
/// @{
|
||||
|
||||
@@ -211,4 +211,8 @@ static inline char *scc_cstring_move_cstr(scc_cstring_t *str) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline scc_cstring_t scc_cstring_move(scc_cstring_t *str) {
|
||||
return scc_cstring_from_cstr(scc_cstring_move_cstr(str));
|
||||
}
|
||||
|
||||
#endif /* __SCC_CORE_STR_H__ */
|
||||
|
||||
@@ -58,6 +58,10 @@ typedef double f64;
|
||||
|
||||
typedef bool cbool;
|
||||
|
||||
#ifndef null
|
||||
#define null NULL
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __SMCC_UTILS_H__
|
||||
#define __SMCC_UTILS_H__
|
||||
|
||||
#include "kllist.h"
|
||||
// #include "kllist.h"
|
||||
#include "scc_hashtable.h"
|
||||
#include "scc_strpool.h"
|
||||
#include <scc_core.h>
|
||||
|
||||
29
src/main.c
29
src/main.c
@@ -226,12 +226,18 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
LOG_FATAL("Failed to open file %s", config.output_file);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fp = scc_stdout;
|
||||
}
|
||||
}
|
||||
|
||||
int error_code = 0;
|
||||
cbool need_end = false;
|
||||
scc_sstream_t sstream;
|
||||
if (scc_sstream_init(&sstream, config.input_file, 1024)) {
|
||||
return 0;
|
||||
error_code = scc_sstream_init(&sstream, config.input_file, 1024);
|
||||
if (error_code) {
|
||||
goto sstream_drop;
|
||||
need_end = true;
|
||||
}
|
||||
|
||||
scc_lexer_t lexer;
|
||||
@@ -244,11 +250,14 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
} else {
|
||||
print_file(tok_ring, fp);
|
||||
}
|
||||
return 0;
|
||||
need_end = true;
|
||||
goto lexer_drop;
|
||||
}
|
||||
|
||||
scc_pproc_t pproc;
|
||||
scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true));
|
||||
// FIXME maybe using config to got download path and add include path
|
||||
scc_pproc_add_include_path_cstr(&pproc, "./.scc_include");
|
||||
scc_vec_foreach(config.include_paths, i) {
|
||||
scc_pproc_add_include_path_cstr(&pproc,
|
||||
scc_vec_at(config.include_paths, i));
|
||||
@@ -266,10 +275,12 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
} else {
|
||||
print_file(tok_ring, fp);
|
||||
}
|
||||
return 0;
|
||||
need_end = true;
|
||||
goto pproc_drop;
|
||||
}
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pproc, 8, false, false);
|
||||
scc_lexer_tok_ring_t *tok_ring =
|
||||
scc_pproc_to_ring(&pproc, 1024, false, false);
|
||||
scc_parser_t parser;
|
||||
scc_sema_callbacks_t sema_callbacks;
|
||||
scc_sema_init(&sema_callbacks);
|
||||
@@ -279,9 +290,15 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
|
||||
scc_sema_drop(&sema_callbacks);
|
||||
scc_parser_drop(&parser);
|
||||
pproc_drop:
|
||||
scc_pproc_drop(&pproc);
|
||||
lexer_drop:
|
||||
scc_lexer_drop(&lexer);
|
||||
sstream_drop:
|
||||
scc_sstream_drop(&sstream);
|
||||
if (error_code || need_end) {
|
||||
return error_code;
|
||||
}
|
||||
|
||||
if (config.emit_ast) {
|
||||
scc_tree_dump_ctx_t tree_dump;
|
||||
@@ -312,6 +329,6 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
scc_printf("output exe at %s", config.output_file);
|
||||
scc_printf("output exe at %s\n", config.output_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -694,12 +694,11 @@ class SccCompiler(Compiler):
|
||||
# cmd = ["clang"] + flags + ["-c", str(source), "-o", str(output)]
|
||||
cmd = [
|
||||
"scc",
|
||||
"--emit-pp",
|
||||
# "--emit-pp",
|
||||
"-T",
|
||||
"-o",
|
||||
str(output),
|
||||
str(source),
|
||||
"-I",
|
||||
"scc_include",
|
||||
]
|
||||
for inc in includes:
|
||||
cmd += ["-I", f"{inc}"]
|
||||
|
||||
Reference in New Issue
Block a user