refactor(log): 统一日志系统并添加链接器实现
- 为所有模块添加统一的 scc_*_log.h 日志头文件,删除旧的 lexer_log.h/c - 将运行时日志从 scc_utils 迁移到 scc_core 目录,统一日志管理 - 在解析器表达式/语句/类型解析中添加 LOG_TRACE 调试日志 - 实现 SCCF 链接器 (sccf_linker) 支持多目标文件链接 - 重构 CLI 主程序 (main.c/config.c),新增 cmd_log.h 调试支持 - 优化 x86 指令编码操作数对齐检查 - 修复预处理器的指令处理和宏展开逻辑
This commit is contained in:
@@ -71,7 +71,6 @@ static inline void scc_parser_reset(scc_parser_t *parser) {
|
||||
scc_ring_reset(*parser->ring);
|
||||
}
|
||||
|
||||
#include <scc_pos_log.h>
|
||||
static inline scc_pos_t scc_parser_got_current_pos(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
|
||||
26
libs/parser/include/scc_parser_log.h
Normal file
26
libs/parser/include/scc_parser_log.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __SCC_PARSER_LOG_H__
|
||||
#define __SCC_PARSER_LOG_H__
|
||||
|
||||
typedef struct logger logger_t;
|
||||
extern logger_t __scc_parser_log;
|
||||
extern logger_t __scc_parser_user;
|
||||
|
||||
#define SCC_LOG_HANDLER &__scc_parser_user
|
||||
#define LOG_DEFAULT_HANDLER &__scc_parser_log
|
||||
#include <scc_log.h>
|
||||
|
||||
#ifdef __SCC_PARSER_LOG_IMPL__
|
||||
logger_t __scc_parser_log = {
|
||||
.name = "parser",
|
||||
.level = LOG_LEVEL_ALL,
|
||||
.handler = log_default_handler,
|
||||
};
|
||||
|
||||
logger_t __scc_parser_user = {
|
||||
.name = "parser",
|
||||
.level = LOG_LEVEL_ALL,
|
||||
.user_handler = scc_log_handler,
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -150,6 +150,7 @@ A.2.4 External definitions
|
||||
declaration
|
||||
declaration-list declaration
|
||||
*/
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_ast_utils.h>
|
||||
@@ -157,6 +158,7 @@ A.2.4 External definitions
|
||||
|
||||
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_ast_expr_t *base) {
|
||||
LOG_DEBUG("scc_parse_initializer()");
|
||||
/*
|
||||
initializer:
|
||||
assignment-expression
|
||||
@@ -179,10 +181,11 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_expr_t *init = nullptr;
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
||||
// TODO int a = 1, b = 1;
|
||||
LOG_TRACE(" simple initializer (assignment-expr)");
|
||||
init = scc_parse_assignment_expression(parser);
|
||||
return init;
|
||||
}
|
||||
LOG_TRACE(" compound initializer {...}");
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
@@ -205,8 +208,11 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
lhs = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
Assert(lhs != nullptr);
|
||||
scc_ast_expr_member_init(lhs, ptr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||
tok.loc);
|
||||
scc_ast_expr_member_init(
|
||||
lhs, ptr,
|
||||
scc_ast_module_intern(parser->ast_module,
|
||||
scc_str_as_cstr(&tok.lexeme)),
|
||||
tok.loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
@@ -261,6 +267,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parse_declaration()");
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
|
||||
scc_ast_decl_t *decl_list = nullptr;
|
||||
@@ -283,12 +290,14 @@ CONTINUE:
|
||||
}
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
||||
LOG_TRACE(" declaration with initializer");
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
// TODO maybe memory leak
|
||||
scc_ast_expr_t *lvalue = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
||||
decl->var.init = scc_parse_initializer(parser, lvalue);
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
LOG_DEBUG(" function definition '%s'", decl->name ? decl->name : "?");
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
|
||||
// 进入函数作用域(用于参数和标签)
|
||||
@@ -317,6 +326,7 @@ CONTINUE:
|
||||
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
||||
LOG_TRACE(" declaration ends with ';'");
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
if (decl_list)
|
||||
scc_vec_push(decl_list_vec, decl);
|
||||
|
||||
@@ -104,6 +104,7 @@ A.2.1 Expressions
|
||||
constant-expression:
|
||||
conditional-expression
|
||||
*/
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_ast_utils.h>
|
||||
@@ -342,6 +343,7 @@ static void parser_sync(scc_parser_t *parser) {
|
||||
|
||||
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
int min_prec) {
|
||||
LOG_TRACE("parse_expression_with_precedence(min_prec=%d)", min_prec);
|
||||
// 从最底层(cast-expression)开始
|
||||
scc_ast_expr_t *left = parse_cast_expression(parser);
|
||||
if (!left)
|
||||
@@ -361,6 +363,7 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
break;
|
||||
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
||||
LOG_TRACE(" binary op=%d at prec=%d", op, prec);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
|
||||
// 解析右操作数(优先级 +1,确保左结合)
|
||||
@@ -377,10 +380,12 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||
left = expr;
|
||||
}
|
||||
LOG_TRACE(" => expr type=%d", left ? left->base.type : -1);
|
||||
return left;
|
||||
}
|
||||
// 赋值表达式(右结合)
|
||||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("scc_parse_assignment_expression()");
|
||||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||||
// unary-expression)
|
||||
scc_ast_expr_t *left = nullptr;
|
||||
@@ -400,6 +405,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
return left;
|
||||
scc_ast_expr_op_t op = map_token_to_assign_op(op_tok.type);
|
||||
LOG_TRACE(" assignment op=%d", op);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
|
||||
// 解析右侧(右结合:继续调用 parse_assignment_expression)
|
||||
@@ -420,6 +426,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
|
||||
// 条件表达式(右结合)
|
||||
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("parse_conditional_expression()");
|
||||
scc_ast_expr_t *cond_expr =
|
||||
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
||||
if (!cond_expr)
|
||||
@@ -466,6 +473,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
|
||||
// 类型转换表达式 (type-name) cast-expression
|
||||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("parse_cast_expression()");
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_qual_type_t *type = nullptr;
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||
@@ -476,6 +484,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
if (type) {
|
||||
// 消耗了类型名后,下一个应该是 ')'
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
LOG_TRACE(" detected type cast");
|
||||
// 是类型转换,解析后面的 cast-expression(注意 cast-expression
|
||||
// 可以嵌套)
|
||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||
@@ -524,6 +533,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
& * + - ~ !
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
LOG_TRACE("parse_unary_expression()");
|
||||
if (!tok_ptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -543,6 +553,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return nullptr;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||||
LOG_TRACE(" unary op=%d", op);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
@@ -574,6 +585,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
|
||||
// sizeof 表达式(特殊处理两种形式)
|
||||
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("parse_sizeof_expression()");
|
||||
scc_lexer_tok_t tok_ptr;
|
||||
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
||||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||
@@ -606,6 +618,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
Assert(type_name != nullptr);
|
||||
LOG_TRACE(" sizeof(type)");
|
||||
scc_ast_expr_sizeof_init(expr, type_name, nullptr, pos);
|
||||
return expr;
|
||||
}
|
||||
@@ -613,6 +626,7 @@ next:
|
||||
// 尝试解析 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (operand != nullptr) {
|
||||
LOG_TRACE(" sizeof(expr)");
|
||||
scc_ast_expr_sizeof_init(expr, nullptr, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
@@ -623,6 +637,7 @@ next:
|
||||
|
||||
// 后缀表达式
|
||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("parse_postfix_expression()");
|
||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
@@ -658,6 +673,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_L_BRACKET: // left[expr]
|
||||
{
|
||||
LOG_TRACE(" postfix: array subscript");
|
||||
if (!scc_parser_next_consume(parser, nullptr))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
@@ -681,6 +697,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
case SCC_TOK_L_PAREN: // left(args)
|
||||
{
|
||||
LOG_TRACE(" postfix: function call");
|
||||
if (!scc_parser_next_consume(parser, nullptr))
|
||||
goto done;
|
||||
pos = left->base.loc;
|
||||
@@ -718,6 +735,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
case SCC_TOK_DOT:
|
||||
case SCC_TOK_DEREF: {
|
||||
LOG_TRACE(" postfix: member access (%s)",
|
||||
tok_ptr->type == SCC_TOK_DOT ? "." : "->");
|
||||
scc_lexer_tok_t op_tok;
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
goto done;
|
||||
@@ -751,6 +770,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
case SCC_TOK_ADD_ADD: // left++
|
||||
case SCC_TOK_SUB_SUB: // left--
|
||||
{
|
||||
LOG_TRACE(" postfix: inc/dec");
|
||||
scc_lexer_tok_t op_tok;
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
goto done;
|
||||
@@ -781,6 +801,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
string-literal
|
||||
( expression )
|
||||
*/
|
||||
LOG_TRACE("parse_primary_expression()");
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return nullptr;
|
||||
@@ -789,6 +810,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *expr = nullptr;
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_IDENT: {
|
||||
LOG_TRACE(" primary: identifier");
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return nullptr;
|
||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
@@ -801,6 +823,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_INT_LITERAL: {
|
||||
LOG_TRACE(" primary: int literal");
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return nullptr;
|
||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
@@ -813,6 +836,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_FLOAT_LITERAL: {
|
||||
LOG_TRACE(" primary: float literal");
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return nullptr;
|
||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
@@ -825,6 +849,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_CHAR_LITERAL: {
|
||||
LOG_TRACE(" primary: char literal");
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return nullptr;
|
||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||
@@ -837,6 +862,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_STRING_LITERAL: {
|
||||
LOG_TRACE(" primary: string literal");
|
||||
scc_str_t string = scc_str_empty();
|
||||
scc_lexer_tok_t tok;
|
||||
while (1) {
|
||||
@@ -863,6 +889,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
LOG_TRACE(" primary: parenthesized expression");
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
expr = scc_parse_expression(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
@@ -882,6 +909,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parse_expression()");
|
||||
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
||||
if (!left)
|
||||
return nullptr;
|
||||
@@ -892,6 +920,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
if (tok_ptr == nullptr || tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
LOG_TRACE(" comma expression");
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
|
||||
@@ -909,6 +938,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parser_constant_expression()");
|
||||
// TODO check constant
|
||||
return parse_conditional_expression(parser);
|
||||
}
|
||||
|
||||
@@ -46,12 +46,14 @@ A.2.3 Statements
|
||||
break ;
|
||||
return expression(opt) ;
|
||||
*/
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_ast_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||
LOG_TRACE("ast_parse_paren_expression()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected '(' before like `( expression )` .");
|
||||
@@ -68,6 +70,7 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||
|
||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_TRACE("parse_label_statement()");
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (!scc_parser_next_consume(parser, &tok)) {
|
||||
return nullptr;
|
||||
@@ -85,12 +88,16 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
|
||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||
Assert(stmt != nullptr);
|
||||
scc_ast_stmt_label_init(stmt, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), statement, pos);
|
||||
scc_ast_stmt_label_init(
|
||||
stmt,
|
||||
scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||
statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_TRACE("parse_case_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -121,6 +128,7 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_TRACE("parse_default_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -143,6 +151,7 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_compound_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -174,6 +183,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_if_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -195,6 +205,7 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
||||
|
||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_switch_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -213,6 +224,7 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_while_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -231,6 +243,7 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_do_while_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -259,6 +272,7 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_for_statement()");
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -314,12 +328,17 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_DEBUG("parse_jump_statement()");
|
||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (scc_parser_next_consume(parser, &tok)) {
|
||||
scc_ast_stmt_goto_init(stmt, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), pos);
|
||||
scc_ast_stmt_goto_init(
|
||||
stmt,
|
||||
scc_ast_module_intern(parser->ast_module,
|
||||
scc_str_as_cstr(&tok.lexeme)),
|
||||
pos);
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected label after goto.");
|
||||
@@ -343,6 +362,7 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
LOG_TRACE("parse_expression_statement()");
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||
@@ -366,6 +386,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parse_statement()");
|
||||
scc_ast_stmt_t *stmt;
|
||||
const scc_lexer_tok_t *tok_ref;
|
||||
tok_ref = scc_parser_peek(parser);
|
||||
@@ -412,6 +433,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_L_BRACE:
|
||||
LOG_TRACE(" stmt: compound");
|
||||
stmt = parse_compound_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
@@ -422,9 +444,11 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
switch ( expression ) statement
|
||||
*/
|
||||
case SCC_TOK_IF:
|
||||
LOG_TRACE(" stmt: if");
|
||||
stmt = parse_if_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_SWITCH:
|
||||
LOG_TRACE(" stmt: switch");
|
||||
stmt = parse_switch_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
@@ -438,12 +462,15 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_WHILE:
|
||||
LOG_TRACE(" stmt: while");
|
||||
stmt = parse_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_DO:
|
||||
LOG_TRACE(" stmt: do-while");
|
||||
stmt = parse_do_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_FOR:
|
||||
LOG_TRACE(" stmt: for");
|
||||
stmt = parse_for_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
@@ -455,9 +482,19 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
return expression(opt) ;
|
||||
*/
|
||||
case SCC_TOK_GOTO:
|
||||
LOG_TRACE(" stmt: goto");
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_CONTINUE:
|
||||
LOG_TRACE(" stmt: continue");
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_BREAK:
|
||||
LOG_TRACE(" stmt: break");
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_RETURN:
|
||||
LOG_TRACE(" stmt: return");
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
default:
|
||||
|
||||
@@ -155,6 +155,7 @@ EXAMPLE The constructions
|
||||
[ constant-expression ]
|
||||
. identifier
|
||||
*/
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parse_type.h>
|
||||
@@ -186,6 +187,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
||||
* - 函数说明符 (inline)
|
||||
*/
|
||||
cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
LOG_TRACE("scc_parse_is_decl_specifier_start()");
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
@@ -230,6 +232,7 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||
LOG_TRACE("scc_parse_is_type_specifier_start()");
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
@@ -551,7 +554,8 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
||||
if (tok_ptr->type == SCC_TOK_IDENT) {
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
name = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme));
|
||||
name = scc_ast_module_intern(parser->ast_module,
|
||||
scc_str_as_cstr(&tok.lexeme));
|
||||
} else if (tok_ptr->type != SCC_TOK_L_BRACE) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected name in struct/union/enum specifier");
|
||||
@@ -581,7 +585,8 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
||||
|
||||
type = scc_parse_got_type(parser, scc_str_as_cstr(&symbol_name));
|
||||
if (type == nullptr) {
|
||||
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||
scc_ast_canon_type_t *canon =
|
||||
scc_ast_module_alloc_type(parser->ast_module);
|
||||
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||
|
||||
scc_ast_node_kind_t decl_kind;
|
||||
@@ -620,6 +625,8 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
||||
|
||||
static scc_ast_qual_type_t *
|
||||
parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) {
|
||||
LOG_DEBUG("parse_struct_union_type(kind=%s)",
|
||||
type_kind == SCC_AST_TYPE_STRUCT ? "struct" : "union");
|
||||
/*
|
||||
(6.7.2.1)
|
||||
struct-or-union-specifier:
|
||||
@@ -699,6 +706,7 @@ parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) {
|
||||
}
|
||||
|
||||
static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
LOG_DEBUG("parse_enum_type()");
|
||||
/*
|
||||
(6.7.2.2)
|
||||
enum-specifier:
|
||||
@@ -749,9 +757,11 @@ static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
scc_ast_decl_t *enum_item_decl =
|
||||
SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||
Assert(enum_item_decl != nullptr);
|
||||
scc_ast_decl_val_init(enum_item_decl, type,
|
||||
scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), enum_item_init,
|
||||
tok.loc);
|
||||
scc_ast_decl_val_init(
|
||||
enum_item_decl, type,
|
||||
scc_ast_module_intern(parser->ast_module,
|
||||
scc_str_as_cstr(&tok.lexeme)),
|
||||
enum_item_init, tok.loc);
|
||||
scc_vec_push(decl->record.fields, enum_item_decl);
|
||||
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
@@ -788,6 +798,7 @@ static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
static scc_ast_qual_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
LOG_TRACE("parse_type_specifier()");
|
||||
type_spec_info_t info = {0};
|
||||
if (!scc_parse_is_type_specifier_start(parser))
|
||||
return nullptr;
|
||||
@@ -927,6 +938,7 @@ duplicate_error:
|
||||
static scc_ast_qual_type_t *
|
||||
parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
||||
scc_ast_qual_type_t **delay_pointee_ptr) {
|
||||
LOG_TRACE("parse_pointer()");
|
||||
/*
|
||||
pointer:
|
||||
* type-qualifier-list(opt)
|
||||
@@ -955,6 +967,7 @@ parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
||||
|
||||
static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
scc_ast_decl_vec_t *params) {
|
||||
LOG_TRACE("parse_parameter_type_list()");
|
||||
/*
|
||||
(6.7.5) parameter-type-list:
|
||||
parameter-list
|
||||
@@ -1110,6 +1123,7 @@ static scc_ast_qual_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
||||
scc_ast_qual_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident) {
|
||||
LOG_TRACE("parse_direct_declarator()");
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_ast_qual_type_t *ret = nullptr;
|
||||
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||
@@ -1200,6 +1214,7 @@ static scc_ast_qual_type_t *
|
||||
parse_direct_abstract_declarator(scc_parser_t *parser,
|
||||
scc_ast_qual_type_t *base,
|
||||
scc_ast_qual_type_t **delay_pointee_ptr) {
|
||||
LOG_TRACE("parse_direct_abstract_declarator()");
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_ast_qual_type_t *ret = nullptr;
|
||||
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||
@@ -1250,6 +1265,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
||||
|
||||
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_qual_type_t *type) {
|
||||
LOG_DEBUG("scc_parse_declarator()");
|
||||
scc_lexer_tok_t decl_name_tok = {0};
|
||||
scc_ast_qual_type_t *decl_type =
|
||||
parse_declarator(parser, type, nullptr, &decl_name_tok);
|
||||
@@ -1260,9 +1276,11 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
decl_name_tok.type == SCC_TOK_UNKNOWN);
|
||||
|
||||
// FIXME memory leak
|
||||
const char *name = decl_name_tok.type == SCC_TOK_IDENT
|
||||
? scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&decl_name_tok.lexeme))
|
||||
: nullptr;
|
||||
const char *name =
|
||||
decl_name_tok.type == SCC_TOK_IDENT
|
||||
? scc_ast_module_intern(parser->ast_module,
|
||||
scc_str_as_cstr(&decl_name_tok.lexeme))
|
||||
: nullptr;
|
||||
|
||||
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, decl_type, name, nullptr,
|
||||
@@ -1297,6 +1315,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parse_declaration_specifiers()");
|
||||
if (!scc_parse_is_decl_specifier_start(parser)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1319,6 +1338,7 @@ scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_qual_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||
LOG_DEBUG("scc_parse_type_name()");
|
||||
if (!(scc_parse_is_type_specifier_start(parser) ||
|
||||
scc_parse_is_type_qualifier_start(parser))) {
|
||||
return nullptr;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define __SCC_PARSER_LOG_IMPL__
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
@@ -55,6 +58,7 @@ void scc_parser_drop(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
LOG_INFO("start parsing translation unit");
|
||||
scc_ast_translation_unit_t *unit =
|
||||
scc_malloc(sizeof(scc_ast_translation_unit_t));
|
||||
if (!unit)
|
||||
@@ -71,6 +75,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
while (1) {
|
||||
scc_ast_decl_t *decl = scc_parse_declaration(parser);
|
||||
if (decl != nullptr) {
|
||||
LOG_DEBUG("parsed declaration type=%d name='%s'", decl->base.type,
|
||||
decl->name ? decl->name : "?");
|
||||
scc_vec_push(unit->declarations, decl);
|
||||
} else {
|
||||
parser->errcode = 1;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <scc_ast_utils.h>
|
||||
#include <scc_pos_log.h>
|
||||
#include <scc_parse_type.h>
|
||||
#include <scc_sema.h>
|
||||
#include <sema_symtab.h>
|
||||
|
||||
@@ -159,6 +161,7 @@ static void expr_callback(scc_sema_ctx_t *sema_ctx,
|
||||
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
||||
return;
|
||||
}
|
||||
LOG_TRACE("sema_expr: type=%d", node_type);
|
||||
scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
||||
scc_ast_node_t *sym_node =
|
||||
@@ -242,6 +245,7 @@ static void stmt_callback(scc_sema_ctx_t *sema_ctx,
|
||||
scc_ast_node_kind_t node_type, void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
||||
|
||||
LOG_TRACE("sema_stmt: node_type=%d", node_type);
|
||||
if (node_type == scc_ast_stmt_t_BEGIN) {
|
||||
if (node == nullptr) {
|
||||
scc_sema_symtab_enter_scope(sema_symtab);
|
||||
@@ -364,6 +368,7 @@ static void decl_callback(scc_sema_ctx_t *sema_ctx,
|
||||
scc_ast_node_kind_t node_type, void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
||||
|
||||
LOG_TRACE("sema_decl: node_type=%d", node_type);
|
||||
// Function declaration scope
|
||||
// FIXME 使用 node_type 区分其他未来的scope
|
||||
if (node_type == scc_ast_decl_t_BEGIN) {
|
||||
@@ -447,6 +452,7 @@ static scc_ast_qual_type_t *got_type_callback(scc_sema_ctx_t *sema_ctx,
|
||||
}
|
||||
|
||||
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_module_t *ast_module) {
|
||||
LOG_DEBUG("scc_sema_init()");
|
||||
sema_ctx->ast_module = ast_module;
|
||||
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
|
||||
if (sema_symtab == nullptr) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <scc_parser_log.h>
|
||||
|
||||
#include <sema_symtab.h>
|
||||
|
||||
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||
@@ -45,12 +47,17 @@ void scc_sema_symtab_leave_scope(scc_sema_symtab_t *symtab) {
|
||||
scc_ast_node_t *scc_sema_symtab_add_symbol(scc_sema_symtab_t *symtab,
|
||||
const char *name,
|
||||
scc_ast_node_t *ast_node_ref) {
|
||||
Assert(name != nullptr && "symbol name must not be null");
|
||||
Assert(ast_node_ref != nullptr && "symbol node must not be null");
|
||||
LOG_TRACE("symtab_add: '%s'", name);
|
||||
return scc_hashtable_set(&symtab->current_scope->symbols, name,
|
||||
ast_node_ref);
|
||||
}
|
||||
|
||||
scc_ast_node_t *scc_sema_symtab_lookup_symbol(scc_sema_symtab_t *symtab,
|
||||
const char *name) {
|
||||
Assert(name != nullptr && "lookup name must not be null");
|
||||
LOG_TRACE("symtab_lookup: '%s'", name);
|
||||
scc_ast_node_t *node = nullptr;
|
||||
for (scc_sema_scope_t *scope = symtab->current_scope; scope != nullptr;
|
||||
scope = scope->parent) {
|
||||
|
||||
Reference in New Issue
Block a user