- 将头文件中的tree_dump.h替换为scc_tree_dump.h - 修改函数签名将scc_tree_dump_ctx_t改为scc_tree_dump_t - 移除过时的宏定义和内联函数实现 - 使用新的scc_tree_dump_* API替代旧的PRINT_*宏 - 简化类型、表达式、语句和声明的转储逻辑 - 统一使用新的树转储接口进行节点和值的输出 feat(ast2ir): 实现逻辑运算符和一元运算符的IR转换 - 添加scc_ast2ir_logical_expr函数处理&&和||运算符 - 实现短路求值逻辑,包含分支控制流 - 添加对一元正号运算符的支持 - 实现取地址和间接寻址运算符 - 添加字符字面量解析支持转义序列 fix(ir): 修复字符串常量构建中的长度计算错误 - 修正数组长度计算从len+1改为len-1 - 调整字符串内容复制逻辑跳过引号边界 - 修正内存分配大小与实际数据长度匹配 refactor(ir): 更新IR转储模块使用统一的树转储接口 - 将IR转储上下文中的tree_dump_ctx_t替换为scc_tree_dump_t - 更新初始化函数签名以使用新的转储接口类型
894 lines
28 KiB
C
894 lines
28 KiB
C
/*
|
||
A.2.1 Expressions
|
||
|
||
(6.5.1)
|
||
primary-expression:
|
||
identifier
|
||
constant
|
||
string-literal
|
||
( expression )
|
||
(6.5.2)
|
||
postfix-expression:
|
||
primary-expression
|
||
postfix-expression [ expression ]
|
||
postfix-expression ( argument-expression-list(opt) )
|
||
postfix-expression . identifier
|
||
postfix-expression -> identifier
|
||
postfix-expression ++
|
||
postfix-expression --
|
||
( type-name ) { initializer-list }
|
||
( type-name ) { initializer-list , }
|
||
(6.5.2)
|
||
argument-expression-list:
|
||
assignment-expression
|
||
argument-expression-list , assignment-expression
|
||
(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
|
||
& * + - ~ !
|
||
(6.5.4)
|
||
cast-expression:
|
||
unary-expression
|
||
( type-name ) cast-expression
|
||
(6.5.5)
|
||
multiplicative-expression:
|
||
cast-expression
|
||
multiplicative-expression * cast-expression
|
||
multiplicative-expression / cast-expression
|
||
multiplicative-expression % cast-expression
|
||
(6.5.6)
|
||
additive-expression:
|
||
multiplicative-expression
|
||
additive-expression + multiplicative-expression
|
||
additive-expression - multiplicative-expression
|
||
(6.5.7)
|
||
shift-expression:
|
||
additive-expression
|
||
shift-expression << additive-expression
|
||
shift-expression >> additive-expression
|
||
(6.5.8)
|
||
relational-expression:
|
||
shift-expression
|
||
relational-expression < shift-expression
|
||
relational-expression > shift-expression
|
||
relational-expression <= shift-expression
|
||
relational-expression >= shift-expression
|
||
(6.5.9)
|
||
equality-expression:
|
||
relational-expression
|
||
equality-expression == relational-expression
|
||
equality-expression != relational-expression
|
||
(6.5.10)
|
||
AND-expression:
|
||
equality-expression
|
||
AND-expression & equality-expression
|
||
(6.5.11)
|
||
exclusive-OR-expression:
|
||
AND-expression
|
||
exclusive-OR-expression ^ AND-expression
|
||
(6.5.12)
|
||
inclusive-OR-expression:
|
||
exclusive-OR-expression
|
||
inclusive-OR-expression | exclusive-OR-expression
|
||
(6.5.13)
|
||
logical-AND-expression:
|
||
inclusive-OR-expression
|
||
logical-AND-expression && inclusive-OR-expression
|
||
(6.5.14)
|
||
logical-OR-expression:
|
||
logical-AND-expression
|
||
logical-OR-expression || logical-AND-expression
|
||
(6.5.15)
|
||
conditional-expression:
|
||
logical-OR-expression
|
||
logical-OR-expression ? expression : conditional-expression
|
||
(6.5.16)
|
||
assignment-expression:
|
||
conditional-expression
|
||
unary-expression assignment-operator assignment-expression
|
||
(6.5.16)
|
||
assignment-operator: one of
|
||
= *= /= %= += -= <<= >>= &= ^= |=
|
||
(6.5.17)
|
||
expression:
|
||
assignment-expression
|
||
expression , assignment-expression
|
||
(6.6)
|
||
constant-expression:
|
||
conditional-expression
|
||
*/
|
||
|
||
#include <parser_utils.h>
|
||
#include <scc_parser.h>
|
||
|
||
/**
|
||
* @brief 运算符优先级定义
|
||
*/
|
||
typedef enum {
|
||
PREC_NONE = 0, // 无优先级
|
||
PREC_COMMA = 1, // ,
|
||
PREC_ASSIGNMENT = 2, // = += -= *= /= %= &= ^= |= <<= >>=
|
||
PREC_CONDITIONAL = 3, // ?:
|
||
PREC_LOGICAL_OR = 4, // ||
|
||
PREC_LOGICAL_AND = 5, // &&
|
||
PREC_BITWISE_OR = 6, // |
|
||
PREC_BITWISE_XOR = 7, // ^
|
||
PREC_BITWISE_AND = 8, // &
|
||
PREC_EQUALITY = 9, // == !=
|
||
PREC_RELATIONAL = 10, // < > <= >=
|
||
PREC_SHIFT = 11, // << >>
|
||
PREC_ADDITIVE = 12, // + -
|
||
PREC_MULTIPLICATIVE = 13, // * / %
|
||
PREC_CAST = 14, // 类型转换
|
||
PREC_UNARY = 15, // ++ -- + - * & ~ ! sizeof
|
||
PREC_POSTFIX = 16, // [] () . -> ++ --
|
||
PREC_PRIMARY = 17, // 最高优先级
|
||
} scc_precedence_t;
|
||
|
||
/* ---------------------------- 函数前向声明 ---------------------------- */
|
||
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||
int min_prec);
|
||
|
||
// 特殊结构:独立解析(右结合、条件、一元、后缀、基本)
|
||
static scc_ast_expr_t *
|
||
parse_conditional_expression(scc_parser_t *parser); // 右结合
|
||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser); // 类型转换
|
||
static scc_ast_expr_t *
|
||
parse_unary_expression(scc_parser_t *parser); // 一元运算符
|
||
static scc_ast_expr_t *
|
||
parse_postfix_expression(scc_parser_t *parser); // 后缀运算符
|
||
static scc_ast_expr_t *
|
||
parse_primary_expression(scc_parser_t *parser); // 基本表达式
|
||
|
||
// 特殊结构的内部辅助函数
|
||
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser);
|
||
|
||
/* ---------------------------- 工具函数 ---------------------------- */
|
||
// 获取 token 的优先级(用于二元运算符)
|
||
static int get_token_precedence(scc_tok_type_t type) {
|
||
switch (type) {
|
||
case SCC_TOK_COMMA:
|
||
return PREC_COMMA;
|
||
// 赋值运算符(右结合,但优先级相同,统一处理)
|
||
case SCC_TOK_ASSIGN:
|
||
case SCC_TOK_ASSIGN_ADD:
|
||
case SCC_TOK_ASSIGN_SUB:
|
||
case SCC_TOK_ASSIGN_MUL:
|
||
case SCC_TOK_ASSIGN_DIV:
|
||
case SCC_TOK_ASSIGN_MOD:
|
||
case SCC_TOK_ASSIGN_AND:
|
||
case SCC_TOK_ASSIGN_OR:
|
||
case SCC_TOK_ASSIGN_XOR:
|
||
case SCC_TOK_ASSIGN_L_SH:
|
||
case SCC_TOK_ASSIGN_R_SH:
|
||
return PREC_ASSIGNMENT;
|
||
case SCC_TOK_COND:
|
||
return PREC_CONDITIONAL;
|
||
case SCC_TOK_OR_OR:
|
||
return PREC_LOGICAL_OR;
|
||
case SCC_TOK_AND_AND:
|
||
return PREC_LOGICAL_AND;
|
||
case SCC_TOK_OR:
|
||
return PREC_BITWISE_OR;
|
||
case SCC_TOK_XOR:
|
||
return PREC_BITWISE_XOR;
|
||
case SCC_TOK_AND:
|
||
return PREC_BITWISE_AND;
|
||
case SCC_TOK_EQ:
|
||
case SCC_TOK_NEQ:
|
||
return PREC_EQUALITY;
|
||
case SCC_TOK_LT:
|
||
case SCC_TOK_GT:
|
||
case SCC_TOK_LE:
|
||
case SCC_TOK_GE:
|
||
return PREC_RELATIONAL;
|
||
case SCC_TOK_L_SH:
|
||
case SCC_TOK_R_SH:
|
||
return PREC_SHIFT;
|
||
case SCC_TOK_ADD:
|
||
case SCC_TOK_SUB:
|
||
return PREC_ADDITIVE;
|
||
case SCC_TOK_MUL:
|
||
case SCC_TOK_DIV:
|
||
case SCC_TOK_MOD:
|
||
return PREC_MULTIPLICATIVE;
|
||
default:
|
||
return PREC_NONE;
|
||
}
|
||
}
|
||
|
||
// 判断 token 是否为二元运算符
|
||
static cbool is_binary_operator(scc_tok_type_t type) {
|
||
return get_token_precedence(type) > PREC_NONE;
|
||
}
|
||
|
||
// 将 token 类型映射为二元操作符(用于 AST)
|
||
static scc_ast_expr_op_t map_token_to_binary_op(scc_tok_type_t type) {
|
||
switch (type) {
|
||
case SCC_TOK_ADD:
|
||
return SCC_AST_OP_ADD;
|
||
case SCC_TOK_SUB:
|
||
return SCC_AST_OP_SUB;
|
||
case SCC_TOK_MUL:
|
||
return SCC_AST_OP_MUL;
|
||
case SCC_TOK_DIV:
|
||
return SCC_AST_OP_DIV;
|
||
case SCC_TOK_MOD:
|
||
return SCC_AST_OP_MOD;
|
||
case SCC_TOK_L_SH:
|
||
return SCC_AST_OP_LEFT_SHIFT;
|
||
case SCC_TOK_R_SH:
|
||
return SCC_AST_OP_RIGHT_SHIFT;
|
||
case SCC_TOK_LT:
|
||
return SCC_AST_OP_LESS;
|
||
case SCC_TOK_GT:
|
||
return SCC_AST_OP_GREATER;
|
||
case SCC_TOK_LE:
|
||
return SCC_AST_OP_LESS_EQUAL;
|
||
case SCC_TOK_GE:
|
||
return SCC_AST_OP_GREATER_EQUAL;
|
||
case SCC_TOK_EQ:
|
||
return SCC_AST_OP_EQUAL;
|
||
case SCC_TOK_NEQ:
|
||
return SCC_AST_OP_NOT_EQUAL;
|
||
case SCC_TOK_AND:
|
||
return SCC_AST_OP_BITWISE_AND;
|
||
case SCC_TOK_XOR:
|
||
return SCC_AST_OP_BITWISE_XOR;
|
||
case SCC_TOK_OR:
|
||
return SCC_AST_OP_BITWISE_OR;
|
||
case SCC_TOK_AND_AND:
|
||
return SCC_AST_OP_LOGICAL_AND;
|
||
case SCC_TOK_OR_OR:
|
||
return SCC_AST_OP_LOGICAL_OR;
|
||
case SCC_TOK_COMMA:
|
||
return SCC_AST_OP_COMMA;
|
||
default:
|
||
return SCC_AST_OP_NONE;
|
||
}
|
||
}
|
||
|
||
// 将 token 类型映射为一元操作符
|
||
static scc_ast_expr_op_t map_token_to_unary_op(scc_tok_type_t type,
|
||
cbool is_prefix) {
|
||
if (is_prefix) {
|
||
switch (type) {
|
||
case SCC_TOK_ADD:
|
||
return SCC_AST_OP_UNARY_PLUS;
|
||
case SCC_TOK_SUB:
|
||
return SCC_AST_OP_UNARY_MINUS;
|
||
case SCC_TOK_AND:
|
||
return SCC_AST_OP_ADDRESS_OF;
|
||
case SCC_TOK_MUL:
|
||
return SCC_AST_OP_INDIRECTION;
|
||
case SCC_TOK_BIT_NOT:
|
||
return SCC_AST_OP_BITWISE_NOT;
|
||
case SCC_TOK_NOT:
|
||
return SCC_AST_OP_LOGICAL_NOT;
|
||
case SCC_TOK_ADD_ADD:
|
||
return SCC_AST_OP_PREFIX_INCREMENT;
|
||
case SCC_TOK_SUB_SUB:
|
||
return SCC_AST_OP_PREFIX_DECREMENT;
|
||
default:
|
||
return SCC_AST_OP_NONE;
|
||
}
|
||
} else {
|
||
switch (type) {
|
||
case SCC_TOK_ADD_ADD:
|
||
return SCC_AST_OP_POSTFIX_INCREMENT;
|
||
case SCC_TOK_SUB_SUB:
|
||
return SCC_AST_OP_POSTFIX_DECREMENT;
|
||
default:
|
||
return SCC_AST_OP_NONE;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 将 token 类型映射为赋值操作符
|
||
static scc_ast_expr_op_t map_token_to_assign_op(scc_tok_type_t type) {
|
||
switch (type) {
|
||
case SCC_TOK_ASSIGN:
|
||
return SCC_AST_OP_ASSIGN;
|
||
case SCC_TOK_ASSIGN_ADD:
|
||
return SCC_AST_OP_ASSIGN_ADD;
|
||
case SCC_TOK_ASSIGN_SUB:
|
||
return SCC_AST_OP_ASSIGN_SUB;
|
||
case SCC_TOK_ASSIGN_MUL:
|
||
return SCC_AST_OP_ASSIGN_MUL;
|
||
case SCC_TOK_ASSIGN_DIV:
|
||
return SCC_AST_OP_ASSIGN_DIV;
|
||
case SCC_TOK_ASSIGN_MOD:
|
||
return SCC_AST_OP_ASSIGN_MOD;
|
||
case SCC_TOK_ASSIGN_AND:
|
||
return SCC_AST_OP_ASSIGN_AND;
|
||
case SCC_TOK_ASSIGN_OR:
|
||
return SCC_AST_OP_ASSIGN_OR;
|
||
case SCC_TOK_ASSIGN_XOR:
|
||
return SCC_AST_OP_ASSIGN_XOR;
|
||
case SCC_TOK_ASSIGN_L_SH:
|
||
return SCC_AST_OP_ASSIGN_LSHIFT;
|
||
case SCC_TOK_ASSIGN_R_SH:
|
||
return SCC_AST_OP_ASSIGN_RSHIFT;
|
||
default:
|
||
return SCC_AST_OP_NONE;
|
||
}
|
||
}
|
||
|
||
// 跳过直到遇到同步 token(分号、右括号、逗号、EOF)
|
||
static void parser_sync(scc_parser_t *parser) {
|
||
const scc_lexer_tok_t *tok_ptr;
|
||
while ((tok_ptr = scc_parser_peek(parser)) != null) {
|
||
scc_tok_type_t type = tok_ptr->type;
|
||
if (type == SCC_TOK_SEMICOLON || type == SCC_TOK_R_PAREN ||
|
||
type == SCC_TOK_R_BRACE || type == SCC_TOK_COMMA ||
|
||
type == SCC_TOK_EOF) {
|
||
break;
|
||
}
|
||
// 消耗并丢弃当前 token
|
||
scc_lexer_tok_t discard;
|
||
if (scc_parser_next_consume(parser, &discard)) {
|
||
scc_lexer_tok_drop(&discard);
|
||
}
|
||
}
|
||
}
|
||
|
||
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||
int min_prec) {
|
||
// 从最底层(cast-expression)开始
|
||
scc_ast_expr_t *left = parse_cast_expression(parser);
|
||
if (!left)
|
||
return null;
|
||
|
||
while (1) {
|
||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||
if (!tok_ptr)
|
||
break;
|
||
int prec = get_token_precedence(tok_ptr->type);
|
||
// 只处理优先级 >= min_prec 的普通二元运算符
|
||
if (prec < min_prec || !is_binary_operator(tok_ptr->type))
|
||
break;
|
||
|
||
// 消费运算符
|
||
scc_lexer_tok_t op_tok;
|
||
if (!scc_parser_next_consume(parser, &op_tok))
|
||
break;
|
||
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
||
scc_lexer_tok_drop(&op_tok);
|
||
|
||
// 解析右操作数(优先级 +1,确保左结合)
|
||
scc_ast_expr_t *right =
|
||
parse_expression_with_precedence(parser, prec + 1);
|
||
if (!right) {
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
// FIXME pos
|
||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||
left = expr;
|
||
}
|
||
return left;
|
||
}
|
||
// 赋值表达式(右结合)
|
||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||
// unary-expression)
|
||
scc_ast_expr_t *left = null;
|
||
left = parse_conditional_expression(parser);
|
||
if (!left)
|
||
return null;
|
||
|
||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||
if (!tok_ptr)
|
||
return left;
|
||
scc_pos_t pos = tok_ptr->loc;
|
||
|
||
int prec = get_token_precedence(tok_ptr->type);
|
||
if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) {
|
||
// 消费赋值运算符
|
||
scc_lexer_tok_t op_tok;
|
||
if (!scc_parser_next_consume(parser, &op_tok))
|
||
return left;
|
||
scc_ast_expr_op_t op = map_token_to_assign_op(op_tok.type);
|
||
scc_lexer_tok_drop(&op_tok);
|
||
|
||
// 解析右侧(右结合:继续调用 parse_assignment_expression)
|
||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||
if (!right) {
|
||
// 错误恢复
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
||
left = expr;
|
||
}
|
||
return left;
|
||
}
|
||
|
||
// 条件表达式(右结合)
|
||
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||
scc_ast_expr_t *cond_expr =
|
||
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
||
if (!cond_expr)
|
||
return null;
|
||
|
||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||
if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
|
||
scc_pos_t pos = tok_ptr->loc;
|
||
// 消耗 '?'
|
||
scc_lexer_tok_t q_tok;
|
||
if (!scc_parser_next_consume(parser, &q_tok))
|
||
return cond_expr;
|
||
scc_lexer_tok_drop(&q_tok);
|
||
|
||
// 解析中间表达式(可以是任何表达式,包括逗号)
|
||
scc_ast_expr_t *then_expr = scc_parse_expression(parser);
|
||
if (!then_expr) {
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
|
||
// 消耗 ':'
|
||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||
"Expected ':' after '?'");
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
|
||
// 解析 else 部分(右结合,再次调用 parse_conditional_expression)
|
||
scc_ast_expr_t *else_expr = parse_conditional_expression(parser);
|
||
if (!else_expr) {
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
|
||
scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(cond != null);
|
||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
||
cond_expr = cond;
|
||
}
|
||
return cond_expr;
|
||
}
|
||
|
||
// 类型转换表达式 (type-name) cast-expression
|
||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||
scc_ast_type_t *type = null;
|
||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
||
// 尝试解析类型名
|
||
scc_parser_store(parser);
|
||
scc_parser_next(parser);
|
||
type = scc_parse_type_name(parser); // 需要外部实现
|
||
if (type) {
|
||
// 消耗了类型名后,下一个应该是 ')'
|
||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||
// 是类型转换,解析后面的 cast-expression(注意 cast-expression
|
||
// 可以嵌套)
|
||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||
if (!operand) {
|
||
// FIXME postfix-expression
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
// FIXME pos
|
||
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
||
operand = scc_parse_initializer(parser, expr);
|
||
return operand;
|
||
}
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
// FIXME pos
|
||
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
||
return expr;
|
||
} else {
|
||
// 不是类型转换,回退
|
||
// 释放 type(假设 scc_parse_type_name 分配了)
|
||
// TODO: scc_ast_type_drop(type);
|
||
scc_parser_restore(parser);
|
||
}
|
||
} else {
|
||
scc_parser_restore(parser);
|
||
// 解析类型名失败,回退
|
||
}
|
||
}
|
||
// 否则作为一元表达式
|
||
return parse_unary_expression(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
|
||
case SCC_TOK_SUB_SUB: // --x
|
||
case SCC_TOK_AND: // &x
|
||
case SCC_TOK_MUL: // *x
|
||
case SCC_TOK_ADD: // +x
|
||
case SCC_TOK_SUB: // -x
|
||
case SCC_TOK_BIT_NOT: // ~x
|
||
case SCC_TOK_NOT: // !x
|
||
{
|
||
if (!scc_parser_next_consume(parser, &tok))
|
||
return null;
|
||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||
scc_pos_t pos = tok.loc;
|
||
scc_lexer_tok_drop(&tok);
|
||
|
||
// 一元运算符右结合,递归调用 parse_unary_expression
|
||
|
||
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;
|
||
}
|
||
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_unary_init(expr, op, operand, pos);
|
||
return expr;
|
||
}
|
||
case SCC_TOK_SIZEOF:
|
||
return parse_sizeof_expression(parser);
|
||
default:
|
||
return parse_postfix_expression(parser);
|
||
}
|
||
}
|
||
|
||
// sizeof 表达式(特殊处理两种形式)
|
||
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||
scc_lexer_tok_t tok_ptr;
|
||
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||
return null;
|
||
}
|
||
scc_pos_t pos = tok_ptr.loc;
|
||
scc_lexer_tok_drop(&tok_ptr);
|
||
|
||
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
||
if (!next) {
|
||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||
"Unexpected end after sizeof");
|
||
return null;
|
||
}
|
||
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
|
||
if (next->type == SCC_TOK_L_PAREN) {
|
||
scc_parser_store(parser);
|
||
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, pos);
|
||
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, pos);
|
||
return expr;
|
||
}
|
||
|
||
// 否则作为 sizeof(type-name)
|
||
return expr;
|
||
}
|
||
|
||
// 后缀表达式
|
||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||
const scc_lexer_tok_t *tok_ptr = null;
|
||
scc_pos_t pos = scc_pos_create();
|
||
if (!left) {
|
||
tok_ptr = scc_parser_peek(parser);
|
||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
|
||
return null;
|
||
}
|
||
pos = tok_ptr->loc;
|
||
|
||
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 ')'");
|
||
}
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
scc_ast_expr_lvalue_init(expr, type, pos);
|
||
left = scc_parse_initializer(parser, expr);
|
||
return left;
|
||
}
|
||
|
||
while (1) {
|
||
tok_ptr = scc_parser_peek(parser);
|
||
if (!tok_ptr)
|
||
break;
|
||
|
||
switch (tok_ptr->type) {
|
||
case SCC_TOK_L_BRACKET: // left[expr]
|
||
{
|
||
if (!scc_parser_next_consume(parser, null))
|
||
return left;
|
||
pos = left->base.loc;
|
||
|
||
scc_ast_expr_t *index = scc_parse_expression(parser);
|
||
if (!index) {
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||
"Expected ']' after subscript");
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(subscript != null);
|
||
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
||
left = subscript;
|
||
break;
|
||
}
|
||
case SCC_TOK_L_PAREN: // left(args)
|
||
{
|
||
if (!scc_parser_next_consume(parser, null))
|
||
return left;
|
||
pos = left->base.loc;
|
||
scc_ast_expr_vec_t args;
|
||
scc_vec_init(args);
|
||
|
||
while (1) {
|
||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN))
|
||
break;
|
||
scc_ast_expr_t *arg = scc_parse_assignment_expression(parser);
|
||
if (!arg) {
|
||
parser_sync(parser);
|
||
break;
|
||
}
|
||
scc_vec_push(args, arg);
|
||
|
||
if (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||
continue;
|
||
} else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN))
|
||
break;
|
||
else {
|
||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||
"Expected ',' or ')' in function call");
|
||
// 释放已解析的参数
|
||
// TODO: 释放 args 中的表达式
|
||
parser_sync(parser);
|
||
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, pos);
|
||
left = call;
|
||
break;
|
||
}
|
||
case SCC_TOK_DOT:
|
||
case SCC_TOK_DEREF: {
|
||
scc_lexer_tok_t op_tok;
|
||
if (!scc_parser_next_consume(parser, &op_tok))
|
||
return left;
|
||
scc_lexer_tok_t ident_tok;
|
||
if (!scc_parser_next_consume(parser, &ident_tok) ||
|
||
ident_tok.type != SCC_TOK_IDENT) {
|
||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||
"Expected identifier after member access");
|
||
scc_lexer_tok_drop(&op_tok);
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
const char *name = scc_str_as_cstr(&ident_tok.lexeme);
|
||
|
||
scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(member != null);
|
||
if (op_tok.type == SCC_TOK_DOT) {
|
||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
||
} else {
|
||
scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc);
|
||
}
|
||
|
||
scc_lexer_tok_drop(&op_tok);
|
||
left = member;
|
||
break;
|
||
}
|
||
case SCC_TOK_ADD_ADD: // left++
|
||
case SCC_TOK_SUB_SUB: // left--
|
||
{
|
||
scc_lexer_tok_t op_tok;
|
||
if (!scc_parser_next_consume(parser, &op_tok))
|
||
return left;
|
||
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
||
scc_lexer_tok_drop(&op_tok);
|
||
left = expr;
|
||
break;
|
||
}
|
||
default:
|
||
goto done;
|
||
}
|
||
}
|
||
done:
|
||
return left;
|
||
}
|
||
|
||
// 基本表达式
|
||
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;
|
||
|
||
scc_lexer_tok_t tok = {0};
|
||
scc_ast_expr_t *expr = null;
|
||
switch (tok_ptr->type) {
|
||
case SCC_TOK_IDENT: {
|
||
if (!scc_parser_next_consume(parser, &tok))
|
||
return null;
|
||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_identifier_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||
tok.loc);
|
||
break;
|
||
}
|
||
case SCC_TOK_INT_LITERAL: {
|
||
if (!scc_parser_next_consume(parser, &tok))
|
||
return null;
|
||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_literal_int_init(expr, scc_str_as_cstr(&tok.lexeme), false,
|
||
tok.loc);
|
||
break;
|
||
}
|
||
case SCC_TOK_FLOAT_LITERAL: {
|
||
if (!scc_parser_next_consume(parser, &tok))
|
||
return null;
|
||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_literal_float_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||
false, tok.loc);
|
||
break;
|
||
}
|
||
case SCC_TOK_CHAR_LITERAL: {
|
||
if (!scc_parser_next_consume(parser, &tok))
|
||
return null;
|
||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_literal_char_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||
false, tok.loc);
|
||
break;
|
||
}
|
||
case SCC_TOK_STRING_LITERAL: {
|
||
scc_str_t string = scc_str_empty();
|
||
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_str_t tmp = scc_str_move(&tok.lexeme);
|
||
scc_lexer_tok_drop(&tok);
|
||
scc_str_append(&string, &tmp);
|
||
}
|
||
|
||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
// FIXME loc
|
||
scc_ast_expr_literal_string_init(expr, scc_str_as_cstr(&string), true,
|
||
tok.loc);
|
||
break;
|
||
}
|
||
case SCC_TOK_L_PAREN:
|
||
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");
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (expr == null) {
|
||
return null;
|
||
}
|
||
scc_parse_expr_sema(parser, expr);
|
||
return expr;
|
||
}
|
||
|
||
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
||
if (!left)
|
||
return null;
|
||
|
||
const scc_lexer_tok_t *tok_ptr = null;
|
||
while (1) {
|
||
tok_ptr = scc_parser_peek(parser);
|
||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) {
|
||
break;
|
||
}
|
||
scc_pos_t pos = tok_ptr->loc;
|
||
scc_parser_next_consume(parser, null);
|
||
|
||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||
if (!right) {
|
||
parser_sync(parser);
|
||
return null;
|
||
}
|
||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||
Assert(expr != null);
|
||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos);
|
||
left = expr;
|
||
}
|
||
return left;
|
||
}
|
||
|
||
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
|
||
// TODO check constant
|
||
return parse_conditional_expression(parser);
|
||
}
|