Files
scc/libs/parser/src/parse_expr.c
zzy ca187c78f1 feat(ast): 更新AST dump功能以使用新的树转储接口
- 将头文件中的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
- 更新初始化函数签名以使用新的转储接口类型
2026-04-03 20:10:51 +08:00

894 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
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-expressionC 标准规定赋值左边必须是
// 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);
}