feat(parser): 改进解析器错误处理和表达式解析逻辑
- 在初始化解析中添加缺失的赋值操作符检查 - 改进后缀表达式解析逻辑,处理嵌套情况 - 添加数组下标初始化的赋值操作符验证 - 修复主表达式解析中的返回语句处理 refactor(pproc): 优化预处理器宏展开和位置追踪 - 添加token复制函数来保持原始位置信息 - 重构宏展开函数参数传递方式 - 修复字符串化参数的位置信息处理 - 改进可变参数宏的处理逻辑 test(parser): 增加标签语句和字符串字面量测试用例 - 添加返回语句with复合字面量的测试 - 增加标签继续语句的测试用例 - 添加字符串连接的解析测试 test(pproc): 添加预处理器位置追踪测试 - 增加双重宏定义位置追踪测试 - 添加带参数宏定义位置追踪测试 - 增加字符串化操作位置追踪测试 docs: 更新代码中的宏定义和注释 - 修正未定义标识符的拼写错误 - 添加必要的头文件包含 - 改进错误消息提示文本
This commit is contained in:
@@ -555,6 +555,7 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
|
||||
PRINT_VALUE(ctx, " %s", stmt->label_stmt.label);
|
||||
}
|
||||
end_node_dump(ctx);
|
||||
dump_child_node((scc_ast_node_t *)stmt->label_stmt.stmt, ctx, true);
|
||||
break;
|
||||
case SCC_AST_STMT_COMPOUND:
|
||||
end_node_dump(ctx);
|
||||
|
||||
@@ -84,7 +84,6 @@ typedef enum scc_cstd {
|
||||
|
||||
#define SCC_CTOK_TABLE \
|
||||
X(unknown , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_UNKNOWN ) \
|
||||
X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED ) \
|
||||
X(EOF , SCC_TOK_SUBTYPE_EOF, SCC_TOK_EOF ) \
|
||||
X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \
|
||||
X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \
|
||||
@@ -160,6 +159,12 @@ typedef enum scc_tok_type {
|
||||
#define X(name, subtype, tok, std) tok,
|
||||
SCC_CKEYWORD_TABLE
|
||||
#undef X
|
||||
|
||||
// FIXME hack one bit for disabled
|
||||
#define X(str, subtype, tok) tok,
|
||||
X(sum , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_SUM )
|
||||
X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED = 1<<7 )
|
||||
#undef X
|
||||
} scc_tok_type_t;
|
||||
/* clang-format on */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -6,6 +6,15 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
|
||||
const scc_pproc_macro_t *macro,
|
||||
scc_lexer_tok_vec_t *tok_buffer);
|
||||
|
||||
static inline scc_lexer_tok_t scc_pproc_tok_copy(scc_pproc_expand_t *ctx,
|
||||
const scc_lexer_tok_t *src) {
|
||||
scc_lexer_tok_t dst = scc_lexer_tok_copy(src);
|
||||
if (ctx->need_keep_org_pos) {
|
||||
dst.loc = ctx->call_pos;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_vec_t *arg_tokens) {
|
||||
// WRITE BY AI
|
||||
@@ -13,8 +22,9 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_cstring_append_ch(&str, '\"'); // 左引号
|
||||
|
||||
int need_space = 0; // 是否需要插入空格
|
||||
scc_lexer_tok_t *tok = null;
|
||||
scc_vec_foreach(*arg_tokens, i) {
|
||||
scc_lexer_tok_t *tok = &scc_vec_at(*arg_tokens, i);
|
||||
tok = &scc_vec_at(*arg_tokens, i);
|
||||
if (tok->type == SCC_TOK_BLANK) {
|
||||
need_space = 1; // 标记遇到空白
|
||||
continue;
|
||||
@@ -39,8 +49,11 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_t result;
|
||||
result.type = SCC_TOK_STRING_LITERAL;
|
||||
result.lexeme = str;
|
||||
if (ctx->need_keep_org_pos)
|
||||
if (ctx->need_keep_org_pos) {
|
||||
result.loc = ctx->call_pos;
|
||||
} else {
|
||||
result.loc = tok ? tok->loc : scc_pos_create();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -88,8 +101,9 @@ RETURN:
|
||||
scc_lexer_drop_ring(ring);
|
||||
scc_lexer_drop(&lexer);
|
||||
scc_sstream_drop(&sstream);
|
||||
if (ctx->need_keep_org_pos)
|
||||
if (ctx->need_keep_org_pos) {
|
||||
result.loc = ctx->call_pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,6 +116,7 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx,
|
||||
copyed_ctx->macro_table = expand_ctx->macro_table;
|
||||
copyed_ctx->need_rescan = false;
|
||||
copyed_ctx->need_parse_defined = expand_ctx->need_parse_defined;
|
||||
copyed_ctx->need_keep_org_pos = expand_ctx->need_keep_org_pos;
|
||||
scc_vec_init(copyed_ctx->output);
|
||||
}
|
||||
|
||||
@@ -394,7 +409,7 @@ static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
|
||||
scc_lexer_tok_vec_t tok_buffer;
|
||||
@@ -403,7 +418,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
Assert(macro->type == SCC_PP_MACRO_FUNCTION);
|
||||
scc_lexer_tok_vec_t raw_args;
|
||||
scc_vec_init(raw_args);
|
||||
scc_pproc_parse_macro_arguments(expand_ctx->input, &raw_args, false);
|
||||
scc_pproc_parse_macro_arguments(ctx->input, &raw_args, false);
|
||||
|
||||
// collect, fill and expand arg
|
||||
scc_pproc_macro_extened_params_t splited_params;
|
||||
@@ -414,15 +429,13 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
|
||||
scc_pproc_macro_extened_params_t expanded_params;
|
||||
scc_vec_init(expanded_params);
|
||||
expand_arguments(&expanded_params, &splited_params, expand_ctx);
|
||||
expand_arguments(&expanded_params, &splited_params, ctx);
|
||||
Assert(scc_vec_size(expanded_params) >= scc_vec_size(macro->params));
|
||||
|
||||
// replace
|
||||
scc_vec_foreach(macro->replaces, i) {
|
||||
scc_lexer_tok_t tok =
|
||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||
if (expand_ctx->need_keep_org_pos)
|
||||
tok.loc = expand_ctx->call_pos;
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||||
@@ -444,8 +457,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro);
|
||||
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
|
||||
|
||||
tok =
|
||||
stringify_argument(expand_ctx, &scc_vec_at(splited_params, j));
|
||||
tok = stringify_argument(ctx, &scc_vec_at(splited_params, j));
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
i = right_idx;
|
||||
continue;
|
||||
@@ -468,11 +480,11 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
Assert(idx < (int)scc_vec_size(splited_params));
|
||||
scc_lexer_tok_vec_t *tok_vec = &scc_vec_at(splited_params, idx);
|
||||
scc_vec_foreach(*tok_vec, j) {
|
||||
scc_vec_push(right_vec,
|
||||
scc_lexer_tok_copy(&scc_vec_at(*tok_vec, j)));
|
||||
scc_vec_push(right_vec, scc_pproc_tok_copy(
|
||||
ctx, &scc_vec_at(*tok_vec, j)));
|
||||
}
|
||||
} else {
|
||||
scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok));
|
||||
scc_vec_push(right_vec, scc_pproc_tok_copy(ctx, right_tok));
|
||||
}
|
||||
|
||||
scc_lexer_tok_t *right =
|
||||
@@ -482,12 +494,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
|
||||
"__VA_ARGS__") == 0) {
|
||||
if (scc_vec_size(right_vec) == 0) {
|
||||
concact(expand_ctx, &tok_buffer, right, true);
|
||||
concact(ctx, &tok_buffer, right, true);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
concact(expand_ctx, &tok_buffer, right, false);
|
||||
concact(ctx, &tok_buffer, right, false);
|
||||
}
|
||||
|
||||
scc_vec_foreach(right_vec, j) {
|
||||
@@ -512,7 +524,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
scc_vec_at(expanded_params, j);
|
||||
scc_lexer_tok_drop(&tok);
|
||||
scc_vec_foreach(expanded_param, k) {
|
||||
tok = scc_lexer_tok_copy(&scc_vec_at(expanded_param, k));
|
||||
tok =
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(expanded_param, k));
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
}
|
||||
continue;
|
||||
@@ -523,20 +536,18 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||
expanded_params_free(&splited_params);
|
||||
expanded_params_free(&expanded_params);
|
||||
|
||||
rescan(expand_ctx, macro, &tok_buffer);
|
||||
rescan(ctx, macro, &tok_buffer);
|
||||
Assert(tok_buffer.cap == 0); // FIXME
|
||||
}
|
||||
|
||||
static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
||||
static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
scc_lexer_tok_vec_t tok_buffer;
|
||||
scc_vec_init(tok_buffer);
|
||||
|
||||
scc_vec_foreach(macro->replaces, i) {
|
||||
scc_lexer_tok_t tok =
|
||||
scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i));
|
||||
if (expand_ctx->need_keep_org_pos)
|
||||
tok.loc = expand_ctx->call_pos;
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
// FIXME using function to warpper it
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
@@ -553,14 +564,14 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
|
||||
right = &scc_vec_at(macro->replaces, right_idx);
|
||||
}
|
||||
|
||||
concact(expand_ctx, &tok_buffer, right, false);
|
||||
concact(ctx, &tok_buffer, right, false);
|
||||
i = right_idx;
|
||||
continue;
|
||||
}
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
}
|
||||
|
||||
rescan(expand_ctx, macro, &tok_buffer);
|
||||
rescan(ctx, macro, &tok_buffer);
|
||||
}
|
||||
|
||||
static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||||
@@ -640,8 +651,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||
|
||||
if (macro == null || need_skip(expand_ctx, macro)) {
|
||||
// FIXME maybe keyword is error or don't parse c keyword or number
|
||||
// 这个地方不太清楚正确的原因
|
||||
tok.type = SCC_TOK_DISABLED;
|
||||
tok.type += SCC_TOK_DISABLED;
|
||||
scc_vec_push(expand_ctx->output, tok);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,14 @@ static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) {
|
||||
cbool ret = false;
|
||||
CONTINUE:
|
||||
ret = pproc_next(pp, tok);
|
||||
// FIXME Hack the token
|
||||
if (ret && tok->type >= SCC_TOK_DISABLED) {
|
||||
tok->type -= SCC_TOK_DISABLED;
|
||||
}
|
||||
|
||||
if (ret && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_INVALID) {
|
||||
PanicFmt("Invalid token: %s", scc_cstring_as_cstr(&tok->lexeme));
|
||||
}
|
||||
if (ret && !pp->ring_need_comment &&
|
||||
scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_COMMENT) {
|
||||
scc_lexer_tok_drop(tok);
|
||||
|
||||
@@ -34,8 +34,105 @@ static void test_define_pos(void) {
|
||||
scc_sstream_drop(&mem_stream);
|
||||
}
|
||||
|
||||
static void test_define_double_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input = "#define _OBJ 1\n#define OBJ _OBJ\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 == 3 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "1") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 3, 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);
|
||||
}
|
||||
|
||||
static void test_define_param_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input = "#define OBJ 1\n#define func(x) x\nfunc(OBJ)";
|
||||
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 == 3 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "1") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 3, 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);
|
||||
}
|
||||
|
||||
static void test_define_stringify_pos(void) {
|
||||
int ret = 0;
|
||||
scc_sstream_t mem_stream;
|
||||
const char *input =
|
||||
"#define _STR(x) #x\n#define STR(x) _STR(x)\n#define OBJ 1\nSTR(OBJ)";
|
||||
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 == 4 && tok.loc.col == 1 &&
|
||||
scc_strcmp(tok.lexeme.data, "\"1\"") == 0);
|
||||
TEST_MSG("Expected: %d:%d:%s", 4, 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),
|
||||
TEST_LIST_CASE(test_define_double_pos),
|
||||
TEST_LIST_CASE(test_define_param_pos),
|
||||
TEST_LIST_CASE(test_define_stringify_pos),
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -541,6 +541,8 @@ static void test_gnu_comma_variadic_deletion(void) {
|
||||
"printf(\"%d\",42)\n");
|
||||
}
|
||||
|
||||
static void test_real_case(void) {}
|
||||
|
||||
static void test_c99_docs(void) {
|
||||
TEST_CASE("6.10.3.3 The ## operator EXAMPLE");
|
||||
CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n"
|
||||
@@ -644,6 +646,8 @@ TEST_LIST = {
|
||||
TEST_LIST_CASE(test_variadic_macros),
|
||||
TEST_LIST_CASE(test_gnu_comma_variadic_deletion),
|
||||
|
||||
TEST_LIST_CASE(test_real_case),
|
||||
|
||||
TEST_LIST_CASE(test_c99_docs),
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__ // GCC, Clang
|
||||
#define __smcc_log_unreachable() (__builtin_unreachable())
|
||||
#define __scc_log_unreachable() (__builtin_unreachable())
|
||||
#elif defined _MSC_VER // MSVC
|
||||
#define __smcc_log_unreachable() (__assume(false))
|
||||
#elif defined __SCC_BUILT_IN__ // The SCC Compiler (my compiler)
|
||||
#define __smcc_log_unreachable() (__smcc_builtin_unreachable())
|
||||
#define __scc_log_unreachable() (__assume(false))
|
||||
#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler)
|
||||
#define __scc_log_unreachable() (__scc_builtin_unreachable())
|
||||
#else
|
||||
#define __smcc_log_unreachable()
|
||||
#define __scc_log_unreachable() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef log_vsnprintf
|
||||
@@ -155,7 +155,7 @@ void log_set_handler(logger_t *logger, log_handler handler);
|
||||
((void)((cond) || \
|
||||
(__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
|
||||
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
|
||||
log_exit(1), __smcc_log_unreachable(), 0)))
|
||||
log_exit(1), __scc_log_unreachable(), 0)))
|
||||
|
||||
/// @name 断言工具宏
|
||||
/// @{
|
||||
|
||||
@@ -211,4 +211,8 @@ static inline char *scc_cstring_move_cstr(scc_cstring_t *str) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline scc_cstring_t scc_cstring_move(scc_cstring_t *str) {
|
||||
return scc_cstring_from_cstr(scc_cstring_move_cstr(str));
|
||||
}
|
||||
|
||||
#endif /* __SCC_CORE_STR_H__ */
|
||||
|
||||
@@ -58,6 +58,10 @@ typedef double f64;
|
||||
|
||||
typedef bool cbool;
|
||||
|
||||
#ifndef null
|
||||
#define null NULL
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
|
||||
29
src/main.c
29
src/main.c
@@ -226,12 +226,18 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
LOG_FATAL("Failed to open file %s", config.output_file);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fp = scc_stdout;
|
||||
}
|
||||
}
|
||||
|
||||
int error_code = 0;
|
||||
cbool need_end = false;
|
||||
scc_sstream_t sstream;
|
||||
if (scc_sstream_init(&sstream, config.input_file, 1024)) {
|
||||
return 0;
|
||||
error_code = scc_sstream_init(&sstream, config.input_file, 1024);
|
||||
if (error_code) {
|
||||
goto sstream_drop;
|
||||
need_end = true;
|
||||
}
|
||||
|
||||
scc_lexer_t lexer;
|
||||
@@ -244,11 +250,14 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
} else {
|
||||
print_file(tok_ring, fp);
|
||||
}
|
||||
return 0;
|
||||
need_end = true;
|
||||
goto lexer_drop;
|
||||
}
|
||||
|
||||
scc_pproc_t pproc;
|
||||
scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true));
|
||||
// FIXME maybe using config to got download path and add include path
|
||||
scc_pproc_add_include_path_cstr(&pproc, "./.scc_include");
|
||||
scc_vec_foreach(config.include_paths, i) {
|
||||
scc_pproc_add_include_path_cstr(&pproc,
|
||||
scc_vec_at(config.include_paths, i));
|
||||
@@ -266,10 +275,12 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
} else {
|
||||
print_file(tok_ring, fp);
|
||||
}
|
||||
return 0;
|
||||
need_end = true;
|
||||
goto pproc_drop;
|
||||
}
|
||||
|
||||
scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pproc, 8, false, false);
|
||||
scc_lexer_tok_ring_t *tok_ring =
|
||||
scc_pproc_to_ring(&pproc, 1024, false, false);
|
||||
scc_parser_t parser;
|
||||
scc_sema_callbacks_t sema_callbacks;
|
||||
scc_sema_init(&sema_callbacks);
|
||||
@@ -279,9 +290,15 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
|
||||
scc_sema_drop(&sema_callbacks);
|
||||
scc_parser_drop(&parser);
|
||||
pproc_drop:
|
||||
scc_pproc_drop(&pproc);
|
||||
lexer_drop:
|
||||
scc_lexer_drop(&lexer);
|
||||
sstream_drop:
|
||||
scc_sstream_drop(&sstream);
|
||||
if (error_code || need_end) {
|
||||
return error_code;
|
||||
}
|
||||
|
||||
if (config.emit_ast) {
|
||||
scc_tree_dump_ctx_t tree_dump;
|
||||
@@ -312,6 +329,6 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
scc_printf("output exe at %s", config.output_file);
|
||||
scc_printf("output exe at %s\n", config.output_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user