feat(ast): 添加复合表达式和初始化器解析支持
重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND, 更新相关结构体定义以支持复合字面量的左右表达式向量表示。 添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能, 包括大括号初始化列表、成员访问和数组下标的处理逻辑。 更新表达式解析器为基于优先级的递归下降解析,修复变量声明中 初始化表达式的内存泄漏问题。 完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
This commit is contained in:
@@ -50,7 +50,7 @@ typedef enum {
|
|||||||
SCC_AST_EXPR_CAST, // 类型转换
|
SCC_AST_EXPR_CAST, // 类型转换
|
||||||
SCC_AST_EXPR_SIZE_OF, // sizeof
|
SCC_AST_EXPR_SIZE_OF, // sizeof
|
||||||
SCC_AST_EXPR_ALIGN_OF, // _Alignof
|
SCC_AST_EXPR_ALIGN_OF, // _Alignof
|
||||||
SCC_AST_EXPR_COMPOUND_LITERAL, // 复合字面量
|
SCC_AST_EXPR_COMPOUND, // 复合字面量
|
||||||
// 字面量
|
// 字面量
|
||||||
SCC_AST_EXPR_INT_LITERAL, // 整数字面量
|
SCC_AST_EXPR_INT_LITERAL, // 整数字面量
|
||||||
SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
|
SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
|
||||||
@@ -310,9 +310,10 @@ struct scc_ast_expr {
|
|||||||
} attr_of;
|
} attr_of;
|
||||||
// 复合字面量
|
// 复合字面量
|
||||||
struct {
|
struct {
|
||||||
scc_ast_type_t *type;
|
scc_ast_expr_t *base;
|
||||||
scc_ast_expr_vec_t init_list;
|
scc_ast_expr_vec_t lhs_exprs;
|
||||||
} compound_literal;
|
scc_ast_expr_vec_t rhs_exprs;
|
||||||
|
} compound;
|
||||||
// 字面量
|
// 字面量
|
||||||
struct {
|
struct {
|
||||||
const char *lexme;
|
const char *lexme;
|
||||||
@@ -323,6 +324,9 @@ struct scc_ast_expr {
|
|||||||
const char *name;
|
const char *name;
|
||||||
scc_ast_decl_t *_target;
|
scc_ast_decl_t *_target;
|
||||||
} identifier;
|
} identifier;
|
||||||
|
struct {
|
||||||
|
scc_ast_type_t *type;
|
||||||
|
} lvalue;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -369,19 +369,28 @@ static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
|||||||
expr->attr_of.expr = null;
|
expr->attr_of.expr = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init can be null
|
// lhs_exprs and rhs_exprs can be null
|
||||||
static inline void
|
static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
|
||||||
scc_ast_expr_compound_literal_init(scc_ast_expr_t *expr, scc_ast_type_t *type,
|
scc_ast_expr_t *base,
|
||||||
scc_ast_expr_vec_t *init) {
|
scc_ast_expr_vec_t *lhs_exprs,
|
||||||
Assert(expr != null && type != null);
|
scc_ast_expr_vec_t *rhs_exprs) {
|
||||||
|
Assert(expr != null && base != null);
|
||||||
expr->base.loc = scc_pos_create();
|
expr->base.loc = scc_pos_create();
|
||||||
expr->base.type = SCC_AST_EXPR_COMPOUND_LITERAL;
|
expr->base.type = SCC_AST_EXPR_COMPOUND;
|
||||||
expr->compound_literal.type = type;
|
expr->compound.base = base;
|
||||||
if (init == null) {
|
|
||||||
scc_vec_init(expr->compound_literal.init_list);
|
if (lhs_exprs == null) {
|
||||||
|
scc_vec_init(expr->compound.lhs_exprs);
|
||||||
} else {
|
} else {
|
||||||
expr->compound_literal.init_list = *init;
|
expr->compound.lhs_exprs = *lhs_exprs;
|
||||||
scc_vec_init(*init);
|
scc_vec_init(*lhs_exprs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rhs_exprs == null) {
|
||||||
|
scc_vec_init(expr->compound.rhs_exprs);
|
||||||
|
} else {
|
||||||
|
expr->compound.rhs_exprs = *rhs_exprs;
|
||||||
|
scc_vec_init(*rhs_exprs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,6 +435,14 @@ static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
|
|||||||
expr->identifier._target = null;
|
expr->identifier._target = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
|
||||||
|
scc_ast_type_t *type) {
|
||||||
|
Assert(expr != null && type != null);
|
||||||
|
expr->base.loc = scc_pos_create();
|
||||||
|
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
|
||||||
|
expr->lvalue.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
// have defined builtin type
|
// have defined builtin type
|
||||||
static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type,
|
static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type,
|
||||||
scc_ast_builtin_type_t builtin) {
|
scc_ast_builtin_type_t builtin) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static const char *node_type_names[] = {
|
|||||||
[SCC_AST_EXPR_CAST] = "CastExpr",
|
[SCC_AST_EXPR_CAST] = "CastExpr",
|
||||||
[SCC_AST_EXPR_SIZE_OF] = "SizeofExpr",
|
[SCC_AST_EXPR_SIZE_OF] = "SizeofExpr",
|
||||||
[SCC_AST_EXPR_ALIGN_OF] = "AlignofExpr",
|
[SCC_AST_EXPR_ALIGN_OF] = "AlignofExpr",
|
||||||
[SCC_AST_EXPR_COMPOUND_LITERAL] = "CompoundLiteralExpr",
|
[SCC_AST_EXPR_COMPOUND] = "CompoundExpr",
|
||||||
[SCC_AST_EXPR_INT_LITERAL] = "IntLiteralExpr",
|
[SCC_AST_EXPR_INT_LITERAL] = "IntLiteralExpr",
|
||||||
[SCC_AST_EXPR_FLOAT_LITERAL] = "FloatLiteralExpr",
|
[SCC_AST_EXPR_FLOAT_LITERAL] = "FloatLiteralExpr",
|
||||||
[SCC_AST_EXPR_CHAR_LITERAL] = "CharLiteralExpr",
|
[SCC_AST_EXPR_CHAR_LITERAL] = "CharLiteralExpr",
|
||||||
@@ -461,15 +461,15 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_AST_EXPR_COMPOUND_LITERAL:
|
case SCC_AST_EXPR_COMPOUND:
|
||||||
dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx,
|
// dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx,
|
||||||
false);
|
// false);
|
||||||
// 初始化列表
|
// // 初始化列表
|
||||||
for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) {
|
// for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) {
|
||||||
dump_child_node(
|
// dump_child_node(
|
||||||
(scc_ast_node_t *)expr->compound_literal.init_list.data[i], ctx,
|
// (scc_ast_node_t *)expr->compound_literal.init_list.data[i],
|
||||||
i == expr->compound_literal.init_list.size - 1);
|
// ctx, i == expr->compound_literal.init_list.size - 1);
|
||||||
}
|
// }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser);
|
|||||||
* @return 声明 AST 节点
|
* @return 声明 AST 节点
|
||||||
*/
|
*/
|
||||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser);
|
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser);
|
||||||
|
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||||
|
scc_ast_expr_t *base);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 解析语句
|
* @brief 解析语句
|
||||||
|
|||||||
@@ -154,6 +154,94 @@ A.2.4 External definitions
|
|||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_parser.h>
|
#include <scc_parser.h>
|
||||||
|
|
||||||
|
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||||
|
scc_ast_expr_t *base) {
|
||||||
|
/*
|
||||||
|
initializer:
|
||||||
|
assignment-expression
|
||||||
|
{ initializer-list }
|
||||||
|
{ initializer-list , }
|
||||||
|
initializer-list:
|
||||||
|
designation(opt) initializer
|
||||||
|
initializer-list , designation(opt) initializer
|
||||||
|
designation:
|
||||||
|
designator-list =
|
||||||
|
designator-list:
|
||||||
|
designator
|
||||||
|
designator-list designator
|
||||||
|
designator:
|
||||||
|
[ constant-expression ]
|
||||||
|
. identifier
|
||||||
|
*/
|
||||||
|
const scc_lexer_tok_t *tok_ptr = null;
|
||||||
|
tok_ptr = scc_parser_peek(parser);
|
||||||
|
scc_ast_expr_t *init = null;
|
||||||
|
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
||||||
|
// TODO int a = 1, b = 1;
|
||||||
|
init = scc_parse_assignment_expression(parser);
|
||||||
|
return init;
|
||||||
|
}
|
||||||
|
scc_parser_next_consume(parser, null);
|
||||||
|
|
||||||
|
init = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
|
Assert(init != null);
|
||||||
|
scc_ast_expr_vec_t lhs_exprs;
|
||||||
|
scc_vec_init(lhs_exprs);
|
||||||
|
scc_ast_expr_vec_t rhs_exprs;
|
||||||
|
scc_vec_init(rhs_exprs);
|
||||||
|
scc_ast_expr_t *lhs = null;
|
||||||
|
scc_ast_expr_t *rhs = null;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
rhs = scc_parse_initializer(parser, lhs);
|
||||||
|
Assert(rhs != null);
|
||||||
|
scc_vec_push(lhs_exprs, lhs);
|
||||||
|
scc_vec_push(rhs_exprs, rhs);
|
||||||
|
} else {
|
||||||
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
|
"Expected 'identifier' after '.'");
|
||||||
|
}
|
||||||
|
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
||||||
|
scc_parser_next_consume(parser, null);
|
||||||
|
scc_ast_expr_t *idx = scc_parser_constant_expression(parser);
|
||||||
|
Assert(idx != null);
|
||||||
|
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||||
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'");
|
||||||
|
}
|
||||||
|
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
|
Assert(lhs != null);
|
||||||
|
scc_ast_expr_array_subscript_init(lhs, base, idx);
|
||||||
|
|
||||||
|
rhs = scc_parse_initializer(parser, lhs);
|
||||||
|
Assert(rhs != null);
|
||||||
|
scc_vec_push(lhs_exprs, lhs);
|
||||||
|
scc_vec_push(rhs_exprs, rhs);
|
||||||
|
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
|
||||||
|
scc_parser_next_consume(parser, null);
|
||||||
|
break;
|
||||||
|
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// FIXME
|
||||||
|
scc_ast_expr_t *expr = scc_parse_initializer(parser, base);
|
||||||
|
scc_vec_push(lhs_exprs, null);
|
||||||
|
scc_vec_push(rhs_exprs, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs);
|
||||||
|
return init;
|
||||||
|
}
|
||||||
|
|
||||||
scc_ast_decl_t *scc_parse_declaration(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_node_t *type_or_decl = _scc_parse_type(parser);
|
||||||
scc_ast_decl_t *decl = null;
|
scc_ast_decl_t *decl = null;
|
||||||
@@ -189,8 +277,10 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
|||||||
goto RETURN;
|
goto RETURN;
|
||||||
} else if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
} else if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
||||||
scc_parser_next_consume(parser, null);
|
scc_parser_next_consume(parser, null);
|
||||||
scc_ast_expr_t *init = scc_parse_expression(parser);
|
// TODO maybe memory leak
|
||||||
decl->var.init = init;
|
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
|
scc_ast_expr_lvalue_init(lvalue, decl->var.type);
|
||||||
|
decl->var.init = scc_parse_initializer(parser, lvalue);
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon");
|
SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,9 +355,9 @@ static scc_ast_expr_op_t map_token_to_assign_op(scc_tok_type_t type) {
|
|||||||
/* ---------------------------- 错误恢复辅助 ---------------------------- */
|
/* ---------------------------- 错误恢复辅助 ---------------------------- */
|
||||||
// 跳过直到遇到同步 token(分号、右括号、逗号、EOF)
|
// 跳过直到遇到同步 token(分号、右括号、逗号、EOF)
|
||||||
static void parser_sync(scc_parser_t *parser) {
|
static void parser_sync(scc_parser_t *parser) {
|
||||||
const scc_lexer_tok_t *tok;
|
const scc_lexer_tok_t *tok_ptr;
|
||||||
while ((tok = scc_parser_peek(parser)) != null) {
|
while ((tok_ptr = scc_parser_peek(parser)) != null) {
|
||||||
scc_tok_type_t type = tok->type;
|
scc_tok_type_t type = tok_ptr->type;
|
||||||
if (type == SCC_TOK_SEMICOLON || type == SCC_TOK_R_PAREN ||
|
if (type == SCC_TOK_SEMICOLON || type == SCC_TOK_R_PAREN ||
|
||||||
type == SCC_TOK_R_BRACE || type == SCC_TOK_COMMA ||
|
type == SCC_TOK_R_BRACE || type == SCC_TOK_COMMA ||
|
||||||
type == SCC_TOK_EOF) {
|
type == SCC_TOK_EOF) {
|
||||||
@@ -411,112 +411,41 @@ static scc_ast_expr_t *create_conditional_expr(scc_parser_t *parser,
|
|||||||
// 其他创建函数根据需要添加(如 call、subscript、member 等)
|
// 其他创建函数根据需要添加(如 call、subscript、member 等)
|
||||||
|
|
||||||
/* ---------------------------- 通用二元解析器 ---------------------------- */
|
/* ---------------------------- 通用二元解析器 ---------------------------- */
|
||||||
/**
|
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||||
* 解析左结合的二元表达式
|
int min_prec) {
|
||||||
* @param parser 解析器
|
// 从最底层(cast-expression)开始
|
||||||
* @param parse_sub 解析下一级(优先级更低)的函数
|
scc_ast_expr_t *left = parse_cast_expression(parser);
|
||||||
* @param this_prec 当前层的优先级
|
if (!left)
|
||||||
* @return 表达式节点
|
|
||||||
*/
|
|
||||||
static scc_ast_expr_t *parse_binary_expression(scc_parser_t *parser,
|
|
||||||
parse_sub_expr_func parse_sub,
|
|
||||||
int this_prec) {
|
|
||||||
scc_ast_expr_t *left = parse_sub(parser);
|
|
||||||
if (!left) {
|
|
||||||
// 左侧解析失败,尝试同步后返回 null
|
|
||||||
parser_sync(parser);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok)
|
if (!tok_ptr)
|
||||||
break;
|
break;
|
||||||
int prec = get_token_precedence(tok->type);
|
int prec = get_token_precedence(tok_ptr->type);
|
||||||
if (prec < this_prec)
|
// 只处理优先级 >= min_prec 的普通二元运算符
|
||||||
break;
|
if (prec < min_prec || !is_binary_operator(tok_ptr->type))
|
||||||
// 必须是二元运算符(但赋值和条件除外,它们已在高层处理,这里不会出现)
|
|
||||||
if (!is_binary_operator(tok->type))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 消费运算符
|
// 消费运算符
|
||||||
scc_lexer_tok_t op_tok;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &op_tok)) {
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
// 消费失败,可能是流结束,退出循环
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
|
|
||||||
// 解析右侧(注意左结合:传入
|
// 解析右操作数(优先级 +1,确保左结合)
|
||||||
// this_prec+1,确保优先级相同的不再结合,避免右结合)
|
|
||||||
scc_ast_expr_t *right =
|
scc_ast_expr_t *right =
|
||||||
parse_binary_expression(parser, parse_sub, this_prec + 1);
|
parse_expression_with_precedence(parser, prec + 1);
|
||||||
if (!right) {
|
if (!right) {
|
||||||
// 右侧解析失败,尝试恢复
|
|
||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
// 释放已构建的 left?这里 left 可能已被使用,简单的做法是向上返回
|
|
||||||
// null
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
left = create_binary_expr(parser, left, right, op);
|
left = create_binary_expr(parser, left, right, op);
|
||||||
if (!left)
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_multiplicative_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_cast_expression,
|
|
||||||
PREC_MULTIPLICATIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_additive_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_multiplicative_expression,
|
|
||||||
PREC_ADDITIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_shift_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_additive_expression,
|
|
||||||
PREC_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_relational_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_shift_expression,
|
|
||||||
PREC_RELATIONAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_equality_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_relational_expression,
|
|
||||||
PREC_EQUALITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_bitwise_and_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_equality_expression,
|
|
||||||
PREC_BITWISE_AND);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_bitwise_xor_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_bitwise_and_expression,
|
|
||||||
PREC_BITWISE_XOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_bitwise_or_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_bitwise_xor_expression,
|
|
||||||
PREC_BITWISE_OR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_logical_and_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_bitwise_or_expression,
|
|
||||||
PREC_LOGICAL_AND);
|
|
||||||
}
|
|
||||||
|
|
||||||
static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser) {
|
|
||||||
return parse_binary_expression(parser, parse_logical_and_expression,
|
|
||||||
PREC_LOGICAL_OR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 赋值表达式(右结合)
|
// 赋值表达式(右结合)
|
||||||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||||||
@@ -526,12 +455,12 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
|||||||
if (!left)
|
if (!left)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok)
|
if (!tok_ptr)
|
||||||
return left;
|
return left;
|
||||||
|
|
||||||
int prec = get_token_precedence(tok->type);
|
int prec = get_token_precedence(tok_ptr->type);
|
||||||
if (prec == PREC_ASSIGNMENT && is_binary_operator(tok->type)) {
|
if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) {
|
||||||
// 消费赋值运算符
|
// 消费赋值运算符
|
||||||
scc_lexer_tok_t op_tok;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
@@ -554,12 +483,13 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// 条件表达式(右结合)
|
// 条件表达式(右结合)
|
||||||
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||||
scc_ast_expr_t *cond = parse_logical_or_expression(parser);
|
scc_ast_expr_t *cond =
|
||||||
|
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
||||||
if (!cond)
|
if (!cond)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok && tok->type == SCC_TOK_COND) {
|
if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
|
||||||
// 消耗 '?'
|
// 消耗 '?'
|
||||||
scc_lexer_tok_t q_tok;
|
scc_lexer_tok_t q_tok;
|
||||||
if (!scc_parser_next_consume(parser, &q_tok))
|
if (!scc_parser_next_consume(parser, &q_tok))
|
||||||
@@ -595,12 +525,13 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// 类型转换表达式 (type-name) cast-expression
|
// 类型转换表达式 (type-name) cast-expression
|
||||||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok && tok->type == SCC_TOK_L_PAREN) {
|
scc_ast_type_t *type = null;
|
||||||
|
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||||
// 尝试解析类型名
|
// 尝试解析类型名
|
||||||
scc_parser_store(parser);
|
scc_parser_store(parser);
|
||||||
scc_parser_next(parser);
|
scc_parser_next(parser);
|
||||||
scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现
|
type = scc_parse_type_name(parser); // 需要外部实现
|
||||||
if (type) {
|
if (type) {
|
||||||
// 消耗了类型名后,下一个应该是 ')'
|
// 消耗了类型名后,下一个应该是 ')'
|
||||||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||||
@@ -620,6 +551,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
|||||||
// 不是类型转换,回退
|
// 不是类型转换,回退
|
||||||
// 释放 type(假设 scc_parse_type_name 分配了)
|
// 释放 type(假设 scc_parse_type_name 分配了)
|
||||||
// TODO: scc_ast_type_drop(type);
|
// TODO: scc_ast_type_drop(type);
|
||||||
|
scc_parser_restore(parser);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scc_parser_restore(parser);
|
scc_parser_restore(parser);
|
||||||
@@ -632,12 +564,12 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// 一元表达式
|
// 一元表达式
|
||||||
static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok)
|
if (!tok_ptr)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// 处理一元运算符
|
// 处理一元运算符
|
||||||
switch (tok->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_ADD_ADD: // ++x
|
case SCC_TOK_ADD_ADD: // ++x
|
||||||
case SCC_TOK_SUB_SUB: // --x
|
case SCC_TOK_SUB_SUB: // --x
|
||||||
case SCC_TOK_AND: // &x
|
case SCC_TOK_AND: // &x
|
||||||
@@ -670,11 +602,12 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// sizeof 表达式(特殊处理两种形式)
|
// sizeof 表达式(特殊处理两种形式)
|
||||||
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||||
scc_lexer_tok_t tok;
|
scc_lexer_tok_t tok_ptr;
|
||||||
if (!scc_parser_next_consume(parser, &tok) || tok.type != SCC_TOK_SIZEOF) {
|
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
||||||
|
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
scc_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok_ptr);
|
||||||
|
|
||||||
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
||||||
if (!next) {
|
if (!next) {
|
||||||
@@ -719,21 +652,41 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
|||||||
// 后缀表达式
|
// 后缀表达式
|
||||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||||
if (!left)
|
const scc_lexer_tok_t *tok_ptr = null;
|
||||||
|
if (!left) {
|
||||||
|
tok_ptr = scc_parser_peek(parser);
|
||||||
|
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
scc_parser_store(parser);
|
||||||
|
scc_parser_next(parser);
|
||||||
|
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||||
|
if (!type) {
|
||||||
|
scc_parser_restore(parser);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
scc_parser_commit(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);
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok)
|
if (!tok_ptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (tok->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_L_BRACKET: // left[expr]
|
case SCC_TOK_L_BRACKET: // left[expr]
|
||||||
{
|
{
|
||||||
scc_lexer_tok_t lb;
|
if (!scc_parser_next_consume(parser, null))
|
||||||
if (!scc_parser_next_consume(parser, &lb))
|
|
||||||
return left;
|
return left;
|
||||||
scc_lexer_tok_drop(&lb);
|
|
||||||
|
|
||||||
scc_ast_expr_t *index = scc_parse_expression(parser);
|
scc_ast_expr_t *index = scc_parse_expression(parser);
|
||||||
if (!index) {
|
if (!index) {
|
||||||
@@ -746,52 +699,45 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *subscript =
|
scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
expr_create(parser, SCC_AST_EXPR_ARRAY_SUBSCRIPT);
|
Assert(subscript != null);
|
||||||
subscript->subscript.array = left;
|
scc_ast_expr_array_subscript_init(subscript, left, index);
|
||||||
subscript->subscript.index = index;
|
|
||||||
left = subscript;
|
left = subscript;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_L_PAREN: // left(args)
|
case SCC_TOK_L_PAREN: // left(args)
|
||||||
{
|
{
|
||||||
scc_lexer_tok_t lp;
|
if (!scc_parser_next_consume(parser, null))
|
||||||
if (!scc_parser_next_consume(parser, &lp))
|
|
||||||
return left;
|
return left;
|
||||||
scc_lexer_tok_drop(&lp);
|
scc_ast_expr_vec_t args;
|
||||||
|
scc_vec_init(args);
|
||||||
|
|
||||||
scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL);
|
|
||||||
call->call.callee = left;
|
|
||||||
scc_vec_init(call->call.args);
|
|
||||||
|
|
||||||
// 解析参数列表
|
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
|
||||||
while (1) {
|
while (1) {
|
||||||
scc_ast_expr_t *arg =
|
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN))
|
||||||
scc_parse_assignment_expression(parser);
|
break;
|
||||||
|
scc_ast_expr_t *arg = scc_parse_assignment_expression(parser);
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
// 释放已解析的参数
|
break;
|
||||||
// TODO: 释放 call->call.args 中的表达式
|
|
||||||
scc_free(call);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
scc_vec_push(call->call.args, arg);
|
scc_vec_push(args, arg);
|
||||||
|
|
||||||
if (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
if (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||||
continue;
|
continue;
|
||||||
} else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
} else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN))
|
||||||
break;
|
break;
|
||||||
} else {
|
else {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
"Expected ',' or ')' in function call");
|
"Expected ',' or ')' in function call");
|
||||||
|
// 释放已解析的参数
|
||||||
|
// TODO: 释放 args 中的表达式
|
||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
// 释放资源
|
|
||||||
scc_free(call);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
|
Assert(call != null);
|
||||||
|
scc_ast_expr_call_init(call, left, &args);
|
||||||
left = call;
|
left = call;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -811,11 +757,13 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
|
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
|
||||||
|
|
||||||
scc_ast_expr_t *member = expr_create(
|
scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
|
||||||
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
|
Assert(member != null);
|
||||||
: SCC_AST_EXPR_PTR_MEMBER);
|
if (op_tok.type == SCC_TOK_DOT) {
|
||||||
member->member.base = left;
|
scc_ast_expr_member_init(member, left, name);
|
||||||
member->member.name = name;
|
} else {
|
||||||
|
scc_ast_expr_ptr_member_init(member, left, name);
|
||||||
|
}
|
||||||
|
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
left = member;
|
left = member;
|
||||||
@@ -842,11 +790,11 @@ done:
|
|||||||
|
|
||||||
// 基本表达式
|
// 基本表达式
|
||||||
static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok)
|
if (!tok_ptr)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
switch (tok->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_IDENT: {
|
case SCC_TOK_IDENT: {
|
||||||
scc_lexer_tok_t ident;
|
scc_lexer_tok_t ident;
|
||||||
if (!scc_parser_next_consume(parser, &ident))
|
if (!scc_parser_next_consume(parser, &ident))
|
||||||
@@ -900,7 +848,6 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
case SCC_TOK_L_PAREN:
|
case SCC_TOK_L_PAREN:
|
||||||
return parse_paren_expression(parser);
|
return parse_paren_expression(parser);
|
||||||
default:
|
default:
|
||||||
parser_sync(parser);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,8 +285,15 @@ cbool scc_parse_is_storage_class_start(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DUP_CHECK(expr) \
|
||||||
|
do { \
|
||||||
|
if (expr) \
|
||||||
|
goto duplicate_error; \
|
||||||
|
expr = true; \
|
||||||
|
} while (0)
|
||||||
static scc_ast_decl_specifier_t
|
static scc_ast_decl_specifier_t
|
||||||
parse_type_qualifier_list(scc_parser_t *parser) {
|
parse_type_qualifier_list(scc_parser_t *parser,
|
||||||
|
scc_ast_decl_specifier_t quals) {
|
||||||
/*
|
/*
|
||||||
(6.7.3)
|
(6.7.3)
|
||||||
type-qualifier:
|
type-qualifier:
|
||||||
@@ -298,7 +305,6 @@ parse_type_qualifier_list(scc_parser_t *parser) {
|
|||||||
type-qualifier
|
type-qualifier
|
||||||
type-qualifier-list type-qualifier
|
type-qualifier-list type-qualifier
|
||||||
*/
|
*/
|
||||||
scc_ast_decl_specifier_t quals = {0};
|
|
||||||
const scc_lexer_tok_t *tok_ptr = null;
|
const scc_lexer_tok_t *tok_ptr = null;
|
||||||
CONTINUE:
|
CONTINUE:
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
@@ -307,21 +313,68 @@ CONTINUE:
|
|||||||
}
|
}
|
||||||
switch (tok_ptr->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_CONST:
|
case SCC_TOK_CONST:
|
||||||
scc_parser_next_consume(parser, null);
|
DUP_CHECK(quals.is_const);
|
||||||
quals.is_const = true;
|
|
||||||
break;
|
break;
|
||||||
case SCC_TOK_RESTRICT:
|
case SCC_TOK_RESTRICT:
|
||||||
scc_parser_next_consume(parser, null);
|
DUP_CHECK(quals.is_restrict);
|
||||||
quals.is_restrict = true;
|
quals.is_restrict = true;
|
||||||
break;
|
break;
|
||||||
case SCC_TOK_VOLATILE:
|
case SCC_TOK_VOLATILE:
|
||||||
scc_parser_next_consume(parser, null);
|
DUP_CHECK(quals.is_volatile);
|
||||||
quals.is_volatile = true;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return quals;
|
return quals;
|
||||||
}
|
}
|
||||||
|
scc_parser_next_consume(parser, null);
|
||||||
goto CONTINUE;
|
goto CONTINUE;
|
||||||
|
duplicate_error:
|
||||||
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||||
|
return quals;
|
||||||
|
}
|
||||||
|
|
||||||
|
static scc_ast_decl_specifier_t
|
||||||
|
parse_declaration_specifiers_list(scc_parser_t *parser,
|
||||||
|
scc_ast_decl_specifier_t quals) {
|
||||||
|
const scc_lexer_tok_t *tok_ptr = null;
|
||||||
|
CONTINUE:
|
||||||
|
tok_ptr = scc_parser_peek(parser);
|
||||||
|
if (tok_ptr == null) {
|
||||||
|
return quals;
|
||||||
|
}
|
||||||
|
switch (tok_ptr->type) {
|
||||||
|
case SCC_TOK_CONST:
|
||||||
|
DUP_CHECK(quals.is_const);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_RESTRICT:
|
||||||
|
DUP_CHECK(quals.is_restrict);
|
||||||
|
quals.is_restrict = true;
|
||||||
|
break;
|
||||||
|
case SCC_TOK_VOLATILE:
|
||||||
|
DUP_CHECK(quals.is_volatile);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_EXTERN:
|
||||||
|
DUP_CHECK(quals.is_extern);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_STATIC:
|
||||||
|
DUP_CHECK(quals.is_static);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_AUTO:
|
||||||
|
DUP_CHECK(quals.is_auto);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_REGISTER:
|
||||||
|
DUP_CHECK(quals.is_register);
|
||||||
|
break;
|
||||||
|
case SCC_TOK_INLINE:
|
||||||
|
DUP_CHECK(quals.is_inline);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return quals;
|
||||||
|
}
|
||||||
|
scc_parser_next_consume(parser, null);
|
||||||
|
goto CONTINUE;
|
||||||
|
duplicate_error:
|
||||||
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||||
|
return quals;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -801,7 +854,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
|||||||
pointee = pointer;
|
pointee = pointer;
|
||||||
}
|
}
|
||||||
scc_ast_type_pointer_init(pointer, pointee);
|
scc_ast_type_pointer_init(pointer, pointee);
|
||||||
pointer->quals = parse_type_qualifier_list(parser);
|
pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
|
||||||
|
|
||||||
return parse_pointer(parser, pointer, delay_pointee_ptr);
|
return parse_pointer(parser, pointer, delay_pointee_ptr);
|
||||||
}
|
}
|
||||||
@@ -890,6 +943,7 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *size = null;
|
scc_ast_expr_t *size = null;
|
||||||
|
scc_ast_decl_specifier_t quals = {0};
|
||||||
if (scc_parse_is_type_qualifier_start(parser)) {
|
if (scc_parse_is_type_qualifier_start(parser)) {
|
||||||
// static assignment-expression
|
// static assignment-expression
|
||||||
// assignment-expression(opt)
|
// assignment-expression(opt)
|
||||||
@@ -904,7 +958,7 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
|||||||
// [ * ]
|
// [ * ]
|
||||||
} else if (scc_parser_consume_if(parser, SCC_TOK_STATIC)) {
|
} else if (scc_parser_consume_if(parser, SCC_TOK_STATIC)) {
|
||||||
// type-qualifier-list(opt) assignment-expression
|
// type-qualifier-list(opt) assignment-expression
|
||||||
parse_type_qualifier_list(parser);
|
parse_type_qualifier_list(parser, quals);
|
||||||
size = scc_parse_expression(parser);
|
size = scc_parse_expression(parser);
|
||||||
} else {
|
} else {
|
||||||
// assignment-expression(opt)
|
// assignment-expression(opt)
|
||||||
@@ -1086,10 +1140,12 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_type_t *ret = null;
|
scc_ast_type_t *ret = null;
|
||||||
scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser);
|
scc_ast_decl_specifier_t spec = {0};
|
||||||
|
spec = parse_declaration_specifiers_list(parser, spec);
|
||||||
ret = parse_type_specifier(parser);
|
ret = parse_type_specifier(parser);
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
ret->quals = spec;
|
ret->quals = spec;
|
||||||
|
ret->quals.is_inline = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_lexer_tok_t tok_ident = {0};
|
scc_lexer_tok_t tok_ident = {0};
|
||||||
@@ -1112,6 +1168,10 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) {
|
|||||||
} else if (decl) {
|
} else if (decl) {
|
||||||
if (type->base.type == SCC_AST_TYPE_FUNCTION) {
|
if (type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||||
scc_ast_decl_func_init(decl, type, name, null);
|
scc_ast_decl_func_init(decl, type, name, null);
|
||||||
|
// TODO using sema to change it
|
||||||
|
if (spec.is_inline) {
|
||||||
|
type->quals.is_inline = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scc_ast_decl_val_init(decl, type, name, null);
|
scc_ast_decl_val_init(decl, type, name, null);
|
||||||
}
|
}
|
||||||
@@ -1127,7 +1187,8 @@ scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_type_t *ret = null;
|
scc_ast_type_t *ret = null;
|
||||||
scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser);
|
scc_ast_decl_specifier_t spec = {0};
|
||||||
|
spec = parse_type_qualifier_list(parser, spec);
|
||||||
ret = parse_type_specifier(parser);
|
ret = parse_type_specifier(parser);
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
ret->quals = spec;
|
ret->quals = spec;
|
||||||
|
|||||||
@@ -507,6 +507,90 @@ static void test_parser_unit(void) {
|
|||||||
scc_parse_translation_unit);
|
scc_parse_translation_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1. 构造参数类型:volatile const char *restrict,并附加 register
|
||||||
|
// 存储类
|
||||||
|
scc_ast_type_t char_type;
|
||||||
|
_scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR);
|
||||||
|
char_type.quals.is_const = true; // const
|
||||||
|
char_type.quals.is_volatile = true; // volatile
|
||||||
|
|
||||||
|
scc_ast_type_t ptr_to_char;
|
||||||
|
scc_ast_type_pointer_init(&ptr_to_char, &char_type);
|
||||||
|
ptr_to_char.quals.is_restrict = true; // restrict 限定指针
|
||||||
|
ptr_to_char.quals.is_register = true; // register 存储类(作用于参数)
|
||||||
|
|
||||||
|
// 2. 参数声明
|
||||||
|
scc_ast_decl_t param_decl;
|
||||||
|
scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt");
|
||||||
|
|
||||||
|
// 3. 返回类型:void *
|
||||||
|
scc_ast_type_t void_type;
|
||||||
|
_scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID);
|
||||||
|
scc_ast_type_t ptr_to_void;
|
||||||
|
scc_ast_type_pointer_init(&ptr_to_void, &void_type);
|
||||||
|
|
||||||
|
// 4. 参数列表
|
||||||
|
scc_ast_decl_vec_t params;
|
||||||
|
scc_vec_init(params);
|
||||||
|
scc_vec_push(params, ¶m_decl);
|
||||||
|
|
||||||
|
// 5. 函数类型(包含 static 和 inline)
|
||||||
|
scc_ast_type_t func_type;
|
||||||
|
scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms);
|
||||||
|
func_type.quals.is_static = true;
|
||||||
|
func_type.quals.is_inline = true;
|
||||||
|
|
||||||
|
// 6. 函数声明
|
||||||
|
scc_ast_decl_t decl;
|
||||||
|
scc_ast_decl_func_init(&decl, &func_type, "call", NULL);
|
||||||
|
|
||||||
|
// 7. 与解析结果比较
|
||||||
|
SCC_CHECK_AST_WITH_SEMA(&decl.base,
|
||||||
|
"static inline void *call(volatile register "
|
||||||
|
"const char *restrict fmt);",
|
||||||
|
scc_parse_declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
scc_ast_expr_t lvalue;
|
||||||
|
scc_ast_expr_lvalue_init(&lvalue, &scc_ast_builtin_type_void);
|
||||||
|
|
||||||
|
scc_ast_expr_t lhs1;
|
||||||
|
scc_ast_expr_member_init(&lhs1, &lvalue, "data");
|
||||||
|
scc_ast_expr_t lhs2;
|
||||||
|
scc_ast_expr_member_init(&lhs2, &lvalue, "size");
|
||||||
|
scc_ast_expr_t lhs3;
|
||||||
|
scc_ast_expr_member_init(&lhs3, &lvalue, "cap");
|
||||||
|
|
||||||
|
scc_ast_expr_t rl0;
|
||||||
|
scc_ast_expr_literal_int_init(&rl0, "0", false);
|
||||||
|
scc_ast_type_t void_ptr;
|
||||||
|
scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void);
|
||||||
|
scc_ast_expr_t rhs1;
|
||||||
|
scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0);
|
||||||
|
scc_ast_expr_t rhs2;
|
||||||
|
scc_ast_expr_literal_int_init(&rhs2, "0", false);
|
||||||
|
scc_ast_expr_t rhs3;
|
||||||
|
scc_ast_expr_literal_int_init(&rhs3, "0", false);
|
||||||
|
|
||||||
|
scc_ast_expr_vec_t lhs_exprs;
|
||||||
|
scc_ast_expr_t *lhs_array[] = {&lhs1, &lhs2, &lhs3};
|
||||||
|
scc_vec_unsafe_from_array(lhs_exprs, lhs_array);
|
||||||
|
|
||||||
|
scc_ast_expr_vec_t rhs_exprs;
|
||||||
|
scc_ast_expr_t *rhs_array[] = {&rhs1, &rhs2, &rhs3};
|
||||||
|
scc_vec_unsafe_from_array(rhs_exprs, rhs_array);
|
||||||
|
|
||||||
|
scc_ast_expr_t expr;
|
||||||
|
scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs);
|
||||||
|
|
||||||
|
// FIXME use real records type
|
||||||
|
SCC_CHECK_AST(&expr.base,
|
||||||
|
"(void){.data = ((void *)0), .size = 0, .cap = 0}",
|
||||||
|
scc_parse_expression);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针)
|
// int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针)
|
||||||
// 步骤:
|
// 步骤:
|
||||||
@@ -1018,7 +1102,7 @@ static void test_parser_type(void) {
|
|||||||
|
|
||||||
// _Complex double
|
// _Complex double
|
||||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double,
|
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double,
|
||||||
"complex double", _scc_parse_type);
|
"double complex", _scc_parse_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 带类型限定符的基本类型 (const, volatile)
|
// 2. 带类型限定符的基本类型 (const, volatile)
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ typedef struct {
|
|||||||
scc_pproc_macro_table_t *expanded_set;
|
scc_pproc_macro_table_t *expanded_set;
|
||||||
scc_lexer_tok_ring_t *input;
|
scc_lexer_tok_ring_t *input;
|
||||||
scc_lexer_tok_vec_t output;
|
scc_lexer_tok_vec_t output;
|
||||||
|
scc_pos_t call_pos;
|
||||||
cbool need_rescan;
|
cbool need_rescan;
|
||||||
cbool need_parse_defined;
|
cbool need_parse_defined;
|
||||||
|
cbool need_keep_org_pos;
|
||||||
} scc_pproc_expand_t;
|
} scc_pproc_expand_t;
|
||||||
|
|
||||||
static inline scc_lexer_tok_ring_t
|
static inline scc_lexer_tok_ring_t
|
||||||
@@ -27,10 +29,11 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx);
|
|||||||
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
||||||
scc_lexer_tok_ring_t *input,
|
scc_lexer_tok_ring_t *input,
|
||||||
scc_lexer_tok_ring_t *output,
|
scc_lexer_tok_ring_t *output,
|
||||||
const scc_pproc_macro_t *macro);
|
const scc_pproc_macro_t *macro,
|
||||||
|
cbool need_keep_org_pos);
|
||||||
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
|
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
|
||||||
scc_lexer_tok_vec_t *input,
|
scc_lexer_tok_vec_t *input,
|
||||||
scc_lexer_tok_vec_t *output,
|
scc_lexer_tok_vec_t *output,
|
||||||
cbool need_parse_defined);
|
cbool need_parse_defined, cbool need_keep_org_pos);
|
||||||
|
|
||||||
#endif /* __SCC_PPROC_EXPAND_H__ */
|
#endif /* __SCC_PPROC_EXPAND_H__ */
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef struct scc_pproc {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
int max_include_depth;
|
int max_include_depth;
|
||||||
|
cbool keep_original_pos;
|
||||||
} config;
|
} config;
|
||||||
} scc_pproc_t;
|
} scc_pproc_t;
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp,
|
|||||||
}
|
}
|
||||||
scc_lexer_tok_vec_t out_vec;
|
scc_lexer_tok_vec_t out_vec;
|
||||||
scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, &out_vec,
|
scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, &out_vec,
|
||||||
need_parse_defined);
|
need_parse_defined, pp->config.keep_original_pos);
|
||||||
*out_ring = scc_lexer_array_to_ring(&out_vec);
|
*out_ring = scc_lexer_array_to_ring(&out_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
|
|||||||
const scc_pproc_macro_t *macro,
|
const scc_pproc_macro_t *macro,
|
||||||
scc_lexer_tok_vec_t *tok_buffer);
|
scc_lexer_tok_vec_t *tok_buffer);
|
||||||
|
|
||||||
static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
|
static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||||
|
scc_lexer_tok_vec_t *arg_tokens) {
|
||||||
// WRITE BY AI
|
// WRITE BY AI
|
||||||
scc_cstring_t str = scc_cstring_create();
|
scc_cstring_t str = scc_cstring_create();
|
||||||
scc_cstring_append_ch(&str, '\"'); // 左引号
|
scc_cstring_append_ch(&str, '\"'); // 左引号
|
||||||
@@ -38,10 +39,13 @@ static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
|
|||||||
scc_lexer_tok_t result;
|
scc_lexer_tok_t result;
|
||||||
result.type = SCC_TOK_STRING_LITERAL;
|
result.type = SCC_TOK_STRING_LITERAL;
|
||||||
result.lexeme = str;
|
result.lexeme = str;
|
||||||
|
if (ctx->need_keep_org_pos)
|
||||||
|
result.loc = ctx->call_pos;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static scc_lexer_tok_t concatenate_tokens(const scc_lexer_tok_t *left,
|
static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx,
|
||||||
|
const scc_lexer_tok_t *left,
|
||||||
const scc_lexer_tok_t *right) {
|
const scc_lexer_tok_t *right) {
|
||||||
scc_cstring_t new_lex = scc_cstring_from_cstr("");
|
scc_cstring_t new_lex = scc_cstring_from_cstr("");
|
||||||
if (left != null) {
|
if (left != null) {
|
||||||
@@ -84,6 +88,8 @@ RETURN:
|
|||||||
scc_lexer_drop_ring(ring);
|
scc_lexer_drop_ring(ring);
|
||||||
scc_lexer_drop(&lexer);
|
scc_lexer_drop(&lexer);
|
||||||
scc_sstream_drop(&sstream);
|
scc_sstream_drop(&sstream);
|
||||||
|
if (ctx->need_keep_org_pos)
|
||||||
|
result.loc = ctx->call_pos;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +108,8 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx,
|
|||||||
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
||||||
scc_lexer_tok_ring_t *input,
|
scc_lexer_tok_ring_t *input,
|
||||||
scc_lexer_tok_ring_t *output,
|
scc_lexer_tok_ring_t *output,
|
||||||
const scc_pproc_macro_t *macro) {
|
const scc_pproc_macro_t *macro,
|
||||||
|
cbool need_keep_org_pos) {
|
||||||
scc_lexer_tok_vec_t expaned_buffer;
|
scc_lexer_tok_vec_t expaned_buffer;
|
||||||
scc_vec_init(expaned_buffer);
|
scc_vec_init(expaned_buffer);
|
||||||
|
|
||||||
@@ -130,7 +137,8 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_lexer_tok_vec_t output_vec;
|
scc_lexer_tok_vec_t output_vec;
|
||||||
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false);
|
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
|
||||||
|
need_keep_org_pos);
|
||||||
Assert(output->cap == 0 && output->data == null); // FIXME hack it
|
Assert(output->cap == 0 && output->data == null); // FIXME hack it
|
||||||
*output = scc_lexer_array_to_ring(&output_vec);
|
*output = scc_lexer_array_to_ring(&output_vec);
|
||||||
}
|
}
|
||||||
@@ -138,13 +146,16 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
|||||||
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
|
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
|
||||||
scc_lexer_tok_vec_t *input,
|
scc_lexer_tok_vec_t *input,
|
||||||
scc_lexer_tok_vec_t *output,
|
scc_lexer_tok_vec_t *output,
|
||||||
cbool need_parse_defined) {
|
cbool need_parse_defined,
|
||||||
|
cbool need_keep_org_pos) {
|
||||||
scc_pproc_expand_t ctx;
|
scc_pproc_expand_t ctx;
|
||||||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input);
|
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input);
|
||||||
ctx.input = ˚
|
ctx.input = ˚
|
||||||
ctx.macro_table = macro_table;
|
ctx.macro_table = macro_table;
|
||||||
ctx.need_rescan = false;
|
ctx.need_rescan = false;
|
||||||
ctx.need_parse_defined = need_parse_defined;
|
ctx.need_parse_defined = need_parse_defined;
|
||||||
|
ctx.need_keep_org_pos = need_keep_org_pos;
|
||||||
|
ctx.call_pos = scc_pos_create();
|
||||||
scc_vec_init(ctx.output);
|
scc_vec_init(ctx.output);
|
||||||
scc_pproc_macro_table_t expanded_set;
|
scc_pproc_macro_table_t expanded_set;
|
||||||
ctx.expanded_set = &expanded_set;
|
ctx.expanded_set = &expanded_set;
|
||||||
@@ -311,7 +322,8 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
|
|||||||
true);
|
true);
|
||||||
scc_lexer_tok_vec_t output = {0};
|
scc_lexer_tok_vec_t output = {0};
|
||||||
scc_pproc_expand_by_vec(expand_ctx->macro_table, &expaned_buffer,
|
scc_pproc_expand_by_vec(expand_ctx->macro_table, &expaned_buffer,
|
||||||
&output, expand_ctx->need_parse_defined);
|
&output, expand_ctx->need_parse_defined,
|
||||||
|
expand_ctx->need_keep_org_pos);
|
||||||
scc_vec_foreach(output, i) {
|
scc_vec_foreach(output, i) {
|
||||||
scc_vec_push(expand_ctx->output, scc_vec_at(output, i));
|
scc_vec_push(expand_ctx->output, scc_vec_at(output, i));
|
||||||
}
|
}
|
||||||
@@ -352,8 +364,8 @@ static inline int got_right_non_blank(int i,
|
|||||||
return right_idx;
|
return right_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right,
|
static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
||||||
cbool gnu_va_arg_extend) {
|
scc_lexer_tok_t *right, cbool gnu_va_arg_extend) {
|
||||||
// ## contact
|
// ## contact
|
||||||
int tok_buf_size = (int)scc_vec_size(*tok_buffer);
|
int tok_buf_size = (int)scc_vec_size(*tok_buffer);
|
||||||
int left_idx = got_left_non_blank(tok_buf_size, tok_buffer);
|
int left_idx = got_left_non_blank(tok_buf_size, tok_buffer);
|
||||||
@@ -369,7 +381,7 @@ static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_lexer_tok_t concate_tok = concatenate_tokens(left, right);
|
scc_lexer_tok_t concate_tok = concatenate_tokens(ctx, left, right);
|
||||||
|
|
||||||
while (left_idx++ < tok_buf_size) {
|
while (left_idx++ < tok_buf_size) {
|
||||||
scc_lexer_tok_drop(&scc_vec_pop(*tok_buffer));
|
scc_lexer_tok_drop(&scc_vec_pop(*tok_buffer));
|
||||||
@@ -409,6 +421,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
|||||||
scc_vec_foreach(macro->replaces, i) {
|
scc_vec_foreach(macro->replaces, i) {
|
||||||
scc_lexer_tok_t tok =
|
scc_lexer_tok_t tok =
|
||||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||||
|
if (expand_ctx->need_keep_org_pos)
|
||||||
|
tok.loc = expand_ctx->call_pos;
|
||||||
if (tok.type == SCC_TOK_BLANK) {
|
if (tok.type == SCC_TOK_BLANK) {
|
||||||
scc_cstring_free(&tok.lexeme);
|
scc_cstring_free(&tok.lexeme);
|
||||||
tok.lexeme = scc_cstring_from_cstr(" ");
|
tok.lexeme = scc_cstring_from_cstr(" ");
|
||||||
@@ -430,7 +444,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
|||||||
int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro);
|
int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro);
|
||||||
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
|
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
|
||||||
|
|
||||||
tok = stringify_argument(&scc_vec_at(splited_params, j));
|
tok =
|
||||||
|
stringify_argument(expand_ctx, &scc_vec_at(splited_params, j));
|
||||||
scc_vec_push(tok_buffer, tok);
|
scc_vec_push(tok_buffer, tok);
|
||||||
i = right_idx;
|
i = right_idx;
|
||||||
continue;
|
continue;
|
||||||
@@ -467,12 +482,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
|||||||
if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
|
if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
|
||||||
"__VA_ARGS__") == 0) {
|
"__VA_ARGS__") == 0) {
|
||||||
if (scc_vec_size(right_vec) == 0) {
|
if (scc_vec_size(right_vec) == 0) {
|
||||||
concact(&tok_buffer, right, true);
|
concact(expand_ctx, &tok_buffer, right, true);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
concact(&tok_buffer, right, false);
|
concact(expand_ctx, &tok_buffer, right, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_vec_foreach(right_vec, j) {
|
scc_vec_foreach(right_vec, j) {
|
||||||
@@ -520,6 +535,8 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
|||||||
scc_vec_foreach(macro->replaces, i) {
|
scc_vec_foreach(macro->replaces, i) {
|
||||||
scc_lexer_tok_t tok =
|
scc_lexer_tok_t tok =
|
||||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||||
|
if (expand_ctx->need_keep_org_pos)
|
||||||
|
tok.loc = expand_ctx->call_pos;
|
||||||
if (tok.type == SCC_TOK_BLANK) {
|
if (tok.type == SCC_TOK_BLANK) {
|
||||||
// FIXME using function to warpper it
|
// FIXME using function to warpper it
|
||||||
scc_cstring_free(&tok.lexeme);
|
scc_cstring_free(&tok.lexeme);
|
||||||
@@ -536,7 +553,7 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
|||||||
right = &scc_vec_at(macro->replaces, right_idx);
|
right = &scc_vec_at(macro->replaces, right_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
concact(&tok_buffer, right, false);
|
concact(expand_ctx, &tok_buffer, right, false);
|
||||||
i = right_idx;
|
i = right_idx;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -630,6 +647,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
|||||||
}
|
}
|
||||||
expand_ctx->need_rescan = true;
|
expand_ctx->need_rescan = true;
|
||||||
|
|
||||||
|
expand_ctx->call_pos = tok.loc;
|
||||||
if (macro->type == SCC_PP_MACRO_OBJECT) {
|
if (macro->type == SCC_PP_MACRO_OBJECT) {
|
||||||
scc_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok);
|
||||||
expand_object_macro(expand_ctx, macro);
|
expand_object_macro(expand_ctx, macro);
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ CONTINUE:
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring,
|
scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring,
|
||||||
&pp->expanded_ring, macro);
|
&pp->expanded_ring, macro,
|
||||||
|
pp->config.keep_original_pos);
|
||||||
goto CONTINUE;
|
goto CONTINUE;
|
||||||
} else {
|
} else {
|
||||||
// continue
|
// continue
|
||||||
@@ -113,6 +114,7 @@ void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) {
|
|||||||
pp->enable = true;
|
pp->enable = true;
|
||||||
|
|
||||||
pp->config.max_include_depth = 32;
|
pp->config.max_include_depth = 32;
|
||||||
|
pp->config.keep_original_pos = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_pproc_add_builtin_macros() {
|
void scc_pproc_add_builtin_macros() {
|
||||||
|
|||||||
41
libs/pproc/tests/test_pproc_pos.c
Normal file
41
libs/pproc/tests/test_pproc_pos.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <scc_pproc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <utest/acutest.h>
|
||||||
|
|
||||||
|
static void test_define_pos(void) {
|
||||||
|
int ret = 0;
|
||||||
|
scc_sstream_t mem_stream;
|
||||||
|
const char *input = "#define OBJ 1\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 == 2 && tok.loc.col == 1 &&
|
||||||
|
scc_strcmp(tok.lexeme.data, "1") == 0);
|
||||||
|
TEST_MSG("Expected: %d:%d:%s", 2, 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),
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
||||||
@@ -15,10 +15,10 @@ int scc_memcmp(const void *s1, const void *s2, usize n);
|
|||||||
* @return u32
|
* @return u32
|
||||||
*/
|
*/
|
||||||
static inline u32 scc_strhash32(const char *s) {
|
static inline u32 scc_strhash32(const char *s) {
|
||||||
u32 hash = 2166136261u; // FNV-1a偏移基础值
|
u32 hash = 2166136261; // FNV-1a偏移基础值
|
||||||
while (*s) {
|
while (*s) {
|
||||||
hash ^= *s++;
|
hash ^= *s++;
|
||||||
hash *= 16777619u;
|
hash *= 16777619;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user