feat(parser): 改进解析器错误处理和表达式解析逻辑
- 在初始化解析中添加缺失的赋值操作符检查 - 改进后缀表达式解析逻辑,处理嵌套情况 - 添加数组下标初始化的赋值操作符验证 - 修复主表达式解析中的返回语句处理 refactor(pproc): 优化预处理器宏展开和位置追踪 - 添加token复制函数来保持原始位置信息 - 重构宏展开函数参数传递方式 - 修复字符串化参数的位置信息处理 - 改进可变参数宏的处理逻辑 test(parser): 增加标签语句和字符串字面量测试用例 - 添加返回语句with复合字面量的测试 - 增加标签继续语句的测试用例 - 添加字符串连接的解析测试 test(pproc): 添加预处理器位置追踪测试 - 增加双重宏定义位置追踪测试 - 添加带参数宏定义位置追踪测试 - 增加字符串化操作位置追踪测试 docs: 更新代码中的宏定义和注释 - 修正未定义标识符的拼写错误 - 添加必要的头文件包含 - 改进错误消息提示文本
This commit is contained in:
@@ -198,13 +198,21 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, null);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
||||
scc_parser_next(parser);
|
||||
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));
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected '='");
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
Assert(rhs != null);
|
||||
if (rhs == null) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected initializer");
|
||||
Panic();
|
||||
}
|
||||
scc_vec_push(lhs_exprs, lhs);
|
||||
scc_vec_push(rhs_exprs, rhs);
|
||||
} else {
|
||||
@@ -221,7 +229,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_array_subscript_init(lhs, base, idx);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '='");
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
Assert(rhs != null);
|
||||
scc_vec_push(lhs_exprs, lhs);
|
||||
@@ -230,6 +240,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, null);
|
||||
break;
|
||||
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
continue;
|
||||
} else {
|
||||
// FIXME
|
||||
|
||||
@@ -480,9 +480,11 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
// 可以嵌套)
|
||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||
if (!operand) {
|
||||
// 释放 type
|
||||
// TODO: 需要 scc_ast_type_drop(type);
|
||||
return null;
|
||||
// FIXME postfix-expression
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
operand = scc_parse_initializer(parser, expr);
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
@@ -576,10 +578,11 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_sizeof_init(null, type);
|
||||
return expr;
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected type-name after sizeof");
|
||||
TODO();
|
||||
}
|
||||
}
|
||||
|
||||
// 否则作为 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (!operand) {
|
||||
@@ -612,12 +615,10 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '{");
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
return scc_parse_initializer(parser, expr);
|
||||
left = scc_parse_initializer(parser, expr);
|
||||
return left;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@@ -779,12 +780,26 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_STRING_LITERAL: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
scc_cstring_t string = scc_cstring_create();
|
||||
scc_lexer_tok_t tok;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
break;
|
||||
}
|
||||
if (tok_ptr->type != SCC_TOK_STRING_LITERAL) {
|
||||
break;
|
||||
}
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_cstring_t tmp = scc_cstring_move(&tok.lexeme);
|
||||
scc_lexer_tok_drop(&tok);
|
||||
scc_cstring_append(&string, &tmp);
|
||||
}
|
||||
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
|
||||
true);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
@@ -807,9 +822,11 @@ static scc_ast_expr_t *parse_paren_expression(scc_parser_t *parser) {
|
||||
// 是类型转换,解析后面的 cast-expression
|
||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||
if (!operand) {
|
||||
// 释放 type
|
||||
// TODO: scc_ast_type_drop(type);
|
||||
return null;
|
||||
// FIXME postfix-expression
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
operand = scc_parse_initializer(parser, expr);
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
|
||||
@@ -80,7 +80,8 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
return null;
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected identifier before like `identifier : statement` .");
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
@@ -364,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
scc_parser_reset(parser);
|
||||
break;
|
||||
}
|
||||
scc_parser_reset(parser);
|
||||
stmt = parse_label_statement(parser);
|
||||
goto RETURN;
|
||||
case SCC_TOK_CASE: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <assert.h>
|
||||
#include <scc_lexer.h>
|
||||
#include <scc_parser.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utest/acutest.h>
|
||||
|
||||
@@ -56,8 +57,9 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
|
||||
char *buffer = _buffer;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
scc_vsnprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer) - 1,
|
||||
fmt, args);
|
||||
int res = scc_vsnprintf(buffer + strlen(buffer),
|
||||
BUFFER_SIZE - strlen(buffer) - 1, fmt, args);
|
||||
Assert(res > 0);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -589,6 +591,24 @@ static void test_parser_unit(void) {
|
||||
SCC_CHECK_AST(&expr.base,
|
||||
"(void){.data = ((void *)0), .size = 0, .cap = 0}",
|
||||
scc_parse_expression);
|
||||
|
||||
scc_ast_stmt_t stmt;
|
||||
scc_ast_stmt_return_init(&stmt, &expr);
|
||||
SCC_CHECK_AST(&stmt.base,
|
||||
"return (void){.data = (void *)0, .size = 0, .cap = 0};",
|
||||
scc_parse_statement);
|
||||
}
|
||||
|
||||
{
|
||||
scc_ast_stmt_t continue_stmt;
|
||||
scc_ast_stmt_continue_init(&continue_stmt);
|
||||
scc_ast_stmt_t stmt;
|
||||
scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt);
|
||||
SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement);
|
||||
|
||||
scc_ast_expr_t str;
|
||||
scc_ast_expr_literal_string_init(&str, "\"ab\"", false);
|
||||
SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user