重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND, 更新相关结构体定义以支持复合字面量的左右表达式向量表示。 添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能, 包括大括号初始化列表、成员访问和数组下标的处理逻辑。 更新表达式解析器为基于优先级的递归下降解析,修复变量声明中 初始化表达式的内存泄漏问题。 完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
669 lines
23 KiB
C
669 lines
23 KiB
C
#include <pproc_expand.h>
|
||
#include <scc_lexer_utils.h>
|
||
#include <scc_pproc.h>
|
||
|
||
static void rescan(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro,
|
||
scc_lexer_tok_vec_t *tok_buffer);
|
||
|
||
static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||
scc_lexer_tok_vec_t *arg_tokens) {
|
||
// WRITE BY AI
|
||
scc_cstring_t str = scc_cstring_create();
|
||
scc_cstring_append_ch(&str, '\"'); // 左引号
|
||
|
||
int need_space = 0; // 是否需要插入空格
|
||
scc_vec_foreach(*arg_tokens, i) {
|
||
scc_lexer_tok_t *tok = &scc_vec_at(*arg_tokens, i);
|
||
if (tok->type == SCC_TOK_BLANK) {
|
||
need_space = 1; // 标记遇到空白
|
||
continue;
|
||
}
|
||
|
||
// 需要空格且当前不是第一个有效token,插入一个空格
|
||
if (need_space && i > 0) {
|
||
scc_cstring_append_ch(&str, ' ');
|
||
}
|
||
|
||
// 对字符串/字符常量内的 " 和 \ 进行转义
|
||
if (tok->type == SCC_TOK_STRING_LITERAL ||
|
||
tok->type == SCC_TOK_CHAR_LITERAL) {
|
||
// 注意:lex包含两端的引号,需要跳过首尾,转义内部字符
|
||
// 简化:暂不处理内部转义,直接追加
|
||
}
|
||
scc_cstring_append(&str, &tok->lexeme);
|
||
need_space = 0;
|
||
}
|
||
scc_cstring_append_ch(&str, '\"'); // 右引号
|
||
|
||
scc_lexer_tok_t result;
|
||
result.type = SCC_TOK_STRING_LITERAL;
|
||
result.lexeme = str;
|
||
if (ctx->need_keep_org_pos)
|
||
result.loc = ctx->call_pos;
|
||
return result;
|
||
}
|
||
|
||
static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx,
|
||
const scc_lexer_tok_t *left,
|
||
const scc_lexer_tok_t *right) {
|
||
scc_cstring_t new_lex = scc_cstring_from_cstr("");
|
||
if (left != null) {
|
||
scc_cstring_append(&new_lex, &left->lexeme);
|
||
}
|
||
if (right != null) {
|
||
scc_cstring_append(&new_lex, &right->lexeme);
|
||
}
|
||
|
||
scc_lexer_t lexer;
|
||
scc_sstream_t sstream;
|
||
// new_lex 所有权转移
|
||
scc_sstream_init_by_buffer(&sstream, scc_cstring_as_cstr(&new_lex),
|
||
scc_cstring_len(&new_lex), true, 8);
|
||
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
|
||
scc_lexer_tok_ring_t *ring = scc_lexer_to_ring(&lexer, 8, true);
|
||
|
||
scc_lexer_tok_t result = {0};
|
||
int ok;
|
||
scc_ring_next_consume(*ring, result, ok);
|
||
if (!ok) {
|
||
result.type = SCC_TOK_EOF;
|
||
goto RETURN; // FIXME maybe memleak
|
||
}
|
||
scc_ring_next_consume(*ring, result, ok);
|
||
if (ok) {
|
||
scc_lexer_tok_drop(&result);
|
||
goto RETURN; // FIXME maybe memleak
|
||
}
|
||
|
||
scc_lexer_tok_t dummy;
|
||
RETURN:
|
||
while (1) {
|
||
scc_ring_next_consume(*ring, dummy, ok);
|
||
if (ok == false) {
|
||
break;
|
||
}
|
||
scc_lexer_tok_drop(&dummy);
|
||
}
|
||
scc_lexer_drop_ring(ring);
|
||
scc_lexer_drop(&lexer);
|
||
scc_sstream_drop(&sstream);
|
||
if (ctx->need_keep_org_pos)
|
||
result.loc = ctx->call_pos;
|
||
return result;
|
||
}
|
||
|
||
static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx,
|
||
scc_pproc_expand_t *copyed_ctx,
|
||
scc_lexer_tok_ring_t *ring) {
|
||
|
||
copyed_ctx->input = ring;
|
||
copyed_ctx->expanded_set = expand_ctx->expanded_set;
|
||
copyed_ctx->macro_table = expand_ctx->macro_table;
|
||
copyed_ctx->need_rescan = false;
|
||
copyed_ctx->need_parse_defined = expand_ctx->need_parse_defined;
|
||
scc_vec_init(copyed_ctx->output);
|
||
}
|
||
|
||
void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
||
scc_lexer_tok_ring_t *input,
|
||
scc_lexer_tok_ring_t *output,
|
||
const scc_pproc_macro_t *macro,
|
||
cbool need_keep_org_pos) {
|
||
scc_lexer_tok_vec_t expaned_buffer;
|
||
scc_vec_init(expaned_buffer);
|
||
|
||
int ok;
|
||
scc_lexer_tok_t tok;
|
||
scc_ring_next_consume(*input, tok, ok);
|
||
if (macro->type == SCC_PP_MACRO_NONE || ok == false) {
|
||
UNREACHABLE();
|
||
} else if (macro->type == SCC_PP_MACRO_OBJECT) {
|
||
scc_vec_push(expaned_buffer, tok);
|
||
} else if (macro->type == SCC_PP_MACRO_FUNCTION) {
|
||
scc_vec_push(expaned_buffer, tok);
|
||
scc_pproc_parse_macro_arguments(input, &expaned_buffer, true);
|
||
}
|
||
while (1) {
|
||
ok = scc_lexer_peek_non_blank(input, &tok);
|
||
if (ok == false) {
|
||
break;
|
||
}
|
||
if (tok.type == SCC_TOK_L_PAREN) {
|
||
scc_pproc_parse_macro_arguments(input, &expaned_buffer, true);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
scc_lexer_tok_vec_t output_vec;
|
||
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
|
||
need_keep_org_pos);
|
||
Assert(output->cap == 0 && output->data == null); // FIXME hack it
|
||
*output = scc_lexer_array_to_ring(&output_vec);
|
||
}
|
||
|
||
void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table,
|
||
scc_lexer_tok_vec_t *input,
|
||
scc_lexer_tok_vec_t *output,
|
||
cbool need_parse_defined,
|
||
cbool need_keep_org_pos) {
|
||
scc_pproc_expand_t ctx;
|
||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input);
|
||
ctx.input = ˚
|
||
ctx.macro_table = macro_table;
|
||
ctx.need_rescan = false;
|
||
ctx.need_parse_defined = need_parse_defined;
|
||
ctx.need_keep_org_pos = need_keep_org_pos;
|
||
ctx.call_pos = scc_pos_create();
|
||
scc_vec_init(ctx.output);
|
||
scc_pproc_macro_table_t expanded_set;
|
||
ctx.expanded_set = &expanded_set;
|
||
|
||
scc_pproc_marco_table_init(ctx.expanded_set);
|
||
scc_pproc_expand_macro(&ctx);
|
||
*output = ctx.output;
|
||
scc_ring_free(*ctx.input);
|
||
scc_pproc_macro_table_drop(ctx.expanded_set);
|
||
}
|
||
|
||
static void disable(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro) {
|
||
scc_pproc_macro_t *expanded_macro =
|
||
scc_pproc_macro_new(¯o->name, macro->type);
|
||
if (expanded_macro == null) {
|
||
LOG_FATAL("Out of memory");
|
||
}
|
||
scc_pproc_macro_table_set(expand_ctx->expanded_set, expanded_macro);
|
||
}
|
||
|
||
static void enable(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro) {
|
||
scc_pproc_macro_table_remove(expand_ctx->expanded_set, ¯o->name);
|
||
}
|
||
|
||
static cbool need_skip(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro) {
|
||
return scc_pproc_macro_table_get(expand_ctx->expanded_set, ¯o->name) !=
|
||
null;
|
||
}
|
||
|
||
static inline void
|
||
split_arguments(scc_pproc_macro_extened_params_t *splited_params,
|
||
scc_lexer_tok_vec_t *raw_args, const scc_pproc_macro_t *macro) {
|
||
scc_lexer_tok_vec_t args;
|
||
scc_vec_init(args);
|
||
|
||
int named_count = (int)scc_vec_size(macro->params);
|
||
cbool is_variadic =
|
||
(named_count > 0 &&
|
||
scc_vec_at(macro->params, named_count - 1).type == SCC_TOK_ELLIPSIS);
|
||
|
||
int depth = 0;
|
||
|
||
scc_vec_foreach(*raw_args, i) {
|
||
scc_lexer_tok_t *raw_arg = &scc_vec_at(*raw_args, i);
|
||
if (raw_arg->type == SCC_TOK_L_PAREN) {
|
||
depth++;
|
||
} else if (raw_arg->type == SCC_TOK_R_PAREN) {
|
||
depth--;
|
||
}
|
||
if (depth != 0 || raw_arg->type != SCC_TOK_COMMA ||
|
||
(is_variadic &&
|
||
(int)scc_vec_size(*splited_params) == named_count - 1)) {
|
||
if (scc_vec_size(args) == 0 && raw_arg->type == SCC_TOK_BLANK) {
|
||
scc_lexer_tok_drop(raw_arg);
|
||
} else {
|
||
scc_lexer_tok_t arg;
|
||
scc_lexer_tok_move(&arg, raw_arg);
|
||
scc_vec_push(args, arg);
|
||
}
|
||
} else {
|
||
scc_lexer_tok_drop(raw_arg);
|
||
if (scc_vec_size(args) &&
|
||
scc_vec_at(args, scc_vec_size(args) - 1).type ==
|
||
SCC_TOK_BLANK) {
|
||
scc_lexer_tok_drop(&scc_vec_pop(args));
|
||
}
|
||
scc_vec_push(*splited_params, args);
|
||
scc_vec_init(args);
|
||
}
|
||
}
|
||
scc_vec_free(*raw_args);
|
||
|
||
if (scc_vec_size(args) &&
|
||
scc_vec_at(args, scc_vec_size(args) - 1).type == SCC_TOK_BLANK) {
|
||
scc_lexer_tok_drop(&scc_vec_pop(args));
|
||
}
|
||
|
||
scc_vec_push(*splited_params, args);
|
||
if (is_variadic && (int)scc_vec_size(*splited_params) == named_count - 1) {
|
||
scc_vec_init(args);
|
||
scc_vec_push(*splited_params, args);
|
||
}
|
||
}
|
||
|
||
static inline void
|
||
expand_arguments(scc_pproc_macro_extened_params_t *expanded_params,
|
||
scc_pproc_macro_extened_params_t *splited_params,
|
||
scc_pproc_expand_t *expand_ctx) {
|
||
scc_vec_foreach(*splited_params, i) {
|
||
scc_pproc_expand_t ctx;
|
||
scc_lexer_tok_vec_t splite_param = scc_vec_at(*splited_params, i);
|
||
scc_lexer_tok_vec_t expanded_param;
|
||
scc_vec_init(expanded_param);
|
||
scc_vec_foreach(splite_param, j) {
|
||
scc_lexer_tok_t tok = scc_vec_at(splite_param, j);
|
||
tok.lexeme = scc_cstring_copy(&tok.lexeme);
|
||
scc_vec_push(expanded_param, tok);
|
||
}
|
||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(&expanded_param);
|
||
scc_copy_expand(expand_ctx, &ctx, &ring);
|
||
scc_pproc_expand_macro(&ctx);
|
||
scc_ring_free(ring);
|
||
scc_vec_push(*expanded_params, ctx.output);
|
||
}
|
||
}
|
||
|
||
static inline void
|
||
expanded_params_free(scc_pproc_macro_extened_params_t *expanded_params) {
|
||
scc_vec_foreach(*expanded_params, i) {
|
||
scc_lexer_tok_vec_t expanded_param = scc_vec_at(*expanded_params, i);
|
||
scc_vec_foreach(expanded_param, j) {
|
||
scc_lexer_tok_t tok = scc_vec_at(expanded_param, j);
|
||
scc_lexer_tok_drop(&tok);
|
||
}
|
||
scc_vec_free(expanded_param);
|
||
}
|
||
scc_vec_free(*expanded_params);
|
||
}
|
||
|
||
static void rescan(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro,
|
||
scc_lexer_tok_vec_t *tok_buffer) {
|
||
scc_pproc_expand_t rescan_ctx;
|
||
|
||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer);
|
||
scc_copy_expand(expand_ctx, &rescan_ctx, &ring);
|
||
|
||
disable(expand_ctx, macro);
|
||
scc_pproc_expand_macro(&rescan_ctx);
|
||
enable(expand_ctx, macro);
|
||
|
||
scc_vec_foreach(rescan_ctx.output, i) {
|
||
scc_vec_push(expand_ctx->output, scc_vec_at(rescan_ctx.output, i));
|
||
}
|
||
|
||
if (scc_vec_size(expand_ctx->output) == 0) {
|
||
goto RETURN;
|
||
}
|
||
|
||
scc_lexer_tok_t *end_tok =
|
||
&scc_vec_at(expand_ctx->output, scc_vec_size(expand_ctx->output) - 1);
|
||
|
||
if (scc_get_tok_subtype(end_tok->type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||
goto RETURN;
|
||
}
|
||
|
||
scc_pproc_macro_t *end_macro =
|
||
scc_pproc_macro_table_get(expand_ctx->macro_table, &end_tok->lexeme);
|
||
if (end_macro == null || end_macro->type != SCC_PP_MACRO_FUNCTION) {
|
||
goto RETURN;
|
||
}
|
||
|
||
int ok = false;
|
||
scc_lexer_tok_t tok;
|
||
ok = scc_lexer_peek_non_blank(expand_ctx->input, &tok);
|
||
if (ok && tok.type == SCC_TOK_L_PAREN) {
|
||
scc_lexer_tok_vec_t expaned_buffer;
|
||
scc_vec_init(expaned_buffer);
|
||
scc_vec_push(expaned_buffer, scc_vec_pop(expand_ctx->output));
|
||
scc_pproc_parse_macro_arguments(expand_ctx->input, &expaned_buffer,
|
||
true);
|
||
scc_lexer_tok_vec_t output = {0};
|
||
scc_pproc_expand_by_vec(expand_ctx->macro_table, &expaned_buffer,
|
||
&output, expand_ctx->need_parse_defined,
|
||
expand_ctx->need_keep_org_pos);
|
||
scc_vec_foreach(output, i) {
|
||
scc_vec_push(expand_ctx->output, scc_vec_at(output, i));
|
||
}
|
||
scc_vec_free(output);
|
||
}
|
||
|
||
RETURN:
|
||
scc_ring_free(*rescan_ctx.input);
|
||
scc_vec_free(rescan_ctx.output);
|
||
}
|
||
|
||
static int find_params(const scc_lexer_tok_t *tok,
|
||
const scc_pproc_macro_t *macro) {
|
||
scc_vec_foreach(macro->params, j) {
|
||
if (scc_cstring_cmp(&(tok->lexeme),
|
||
&(scc_vec_at(macro->params, j).lexeme)) == 0) {
|
||
return j;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
static inline int got_left_non_blank(int i,
|
||
const scc_lexer_tok_vec_t *replaces) {
|
||
int left_idx = i - 1;
|
||
while (left_idx >= 0 &&
|
||
scc_vec_at(*replaces, left_idx).type == SCC_TOK_BLANK) {
|
||
left_idx--;
|
||
}
|
||
return left_idx;
|
||
}
|
||
static inline int got_right_non_blank(int i,
|
||
const scc_lexer_tok_vec_t *replaces) {
|
||
int right_idx = i + 1;
|
||
while (right_idx < (int)scc_vec_size(*replaces) &&
|
||
scc_vec_at(*replaces, right_idx).type == SCC_TOK_BLANK) {
|
||
right_idx++;
|
||
}
|
||
return right_idx;
|
||
}
|
||
|
||
static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
||
scc_lexer_tok_t *right, cbool gnu_va_arg_extend) {
|
||
// ## contact
|
||
int tok_buf_size = (int)scc_vec_size(*tok_buffer);
|
||
int left_idx = got_left_non_blank(tok_buf_size, tok_buffer);
|
||
|
||
scc_lexer_tok_t *left;
|
||
if (left_idx < 0) {
|
||
left = null;
|
||
left_idx = 0; // FIXME for free tok_buffer
|
||
} else {
|
||
left = &scc_vec_at(*tok_buffer, left_idx);
|
||
if (gnu_va_arg_extend && left->type == SCC_TOK_COMMA) {
|
||
left = null;
|
||
}
|
||
}
|
||
|
||
scc_lexer_tok_t concate_tok = concatenate_tokens(ctx, left, right);
|
||
|
||
while (left_idx++ < tok_buf_size) {
|
||
scc_lexer_tok_drop(&scc_vec_pop(*tok_buffer));
|
||
}
|
||
if (concate_tok.type == SCC_TOK_UNKNOWN) {
|
||
LOG_FATAL("Invalid ## token");
|
||
}
|
||
if (concate_tok.type != SCC_TOK_EOF) {
|
||
scc_vec_push(*tok_buffer, concate_tok);
|
||
}
|
||
}
|
||
|
||
static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||
const scc_pproc_macro_t *macro) {
|
||
|
||
scc_lexer_tok_vec_t tok_buffer;
|
||
scc_vec_init(tok_buffer);
|
||
|
||
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);
|
||
|
||
// collect, fill and expand arg
|
||
scc_pproc_macro_extened_params_t splited_params;
|
||
scc_vec_init(splited_params);
|
||
split_arguments(&splited_params, &raw_args, macro);
|
||
Assert(raw_args.cap == 0); // FIXME
|
||
Assert(scc_vec_size(splited_params) >= scc_vec_size(macro->params));
|
||
|
||
scc_pproc_macro_extened_params_t expanded_params;
|
||
scc_vec_init(expanded_params);
|
||
expand_arguments(&expanded_params, &splited_params, expand_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;
|
||
if (tok.type == SCC_TOK_BLANK) {
|
||
scc_cstring_free(&tok.lexeme);
|
||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||
scc_vec_push(tok_buffer, tok);
|
||
continue;
|
||
}
|
||
|
||
if (tok.type == SCC_TOK_SHARP) {
|
||
// # stringify
|
||
scc_lexer_tok_drop(&tok);
|
||
int right_idx = got_right_non_blank(i, ¯o->replaces);
|
||
if (right_idx >= (int)macro->replaces.size) {
|
||
LOG_WARN("generate empty stringify");
|
||
scc_cstring_free(&tok.lexeme);
|
||
tok.lexeme = scc_cstring_from_cstr("");
|
||
scc_vec_push(tok_buffer, tok);
|
||
break;
|
||
}
|
||
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));
|
||
scc_vec_push(tok_buffer, tok);
|
||
i = right_idx;
|
||
continue;
|
||
} else if (tok.type == SCC_TOK_SHARP_SHARP) {
|
||
// ## contact
|
||
scc_lexer_tok_drop(&tok);
|
||
int right_idx = got_right_non_blank(i, ¯o->replaces);
|
||
|
||
scc_lexer_tok_t *right_tok;
|
||
if (right_idx >= (int)scc_vec_size(macro->replaces)) {
|
||
right_tok = null;
|
||
} else {
|
||
right_tok = &scc_vec_at(macro->replaces, right_idx);
|
||
}
|
||
|
||
int idx = find_params(right_tok, macro);
|
||
scc_lexer_tok_vec_t right_vec;
|
||
scc_vec_init(right_vec);
|
||
if (idx != -1) {
|
||
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)));
|
||
}
|
||
} else {
|
||
scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok));
|
||
}
|
||
|
||
scc_lexer_tok_t *right =
|
||
scc_vec_size(right_vec) ? &scc_vec_at(right_vec, 0) : null;
|
||
|
||
// GNU ## extention
|
||
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);
|
||
} else {
|
||
continue;
|
||
}
|
||
} else {
|
||
concact(expand_ctx, &tok_buffer, right, false);
|
||
}
|
||
|
||
scc_vec_foreach(right_vec, j) {
|
||
if (j == 0) {
|
||
scc_lexer_tok_drop(&scc_vec_at(right_vec, j));
|
||
continue;
|
||
}
|
||
scc_lexer_tok_t tok = {0};
|
||
scc_lexer_tok_move(&tok, &scc_vec_at(right_vec, j));
|
||
scc_lexer_tok_drop(&scc_vec_at(right_vec, j));
|
||
scc_vec_push(tok_buffer, tok);
|
||
}
|
||
scc_vec_free(right_vec);
|
||
|
||
i = right_idx;
|
||
continue;
|
||
} else {
|
||
int j = find_params(&tok, macro);
|
||
if (j != -1) {
|
||
Assert(j < (int)scc_vec_size(expanded_params));
|
||
scc_lexer_tok_vec_t expanded_param =
|
||
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));
|
||
scc_vec_push(tok_buffer, tok);
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
scc_vec_push(tok_buffer, tok);
|
||
}
|
||
expanded_params_free(&splited_params);
|
||
expanded_params_free(&expanded_params);
|
||
|
||
rescan(expand_ctx, macro, &tok_buffer);
|
||
Assert(tok_buffer.cap == 0); // FIXME
|
||
}
|
||
|
||
static inline void expand_object_macro(scc_pproc_expand_t *expand_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;
|
||
if (tok.type == SCC_TOK_BLANK) {
|
||
// FIXME using function to warpper it
|
||
scc_cstring_free(&tok.lexeme);
|
||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||
} else if (tok.type == SCC_TOK_SHARP_SHARP) {
|
||
// ## contact
|
||
scc_lexer_tok_drop(&tok);
|
||
int right_idx = got_right_non_blank(i, ¯o->replaces);
|
||
|
||
scc_lexer_tok_t *right;
|
||
if (right_idx >= (int)scc_vec_size(macro->replaces)) {
|
||
right = null;
|
||
} else {
|
||
right = &scc_vec_at(macro->replaces, right_idx);
|
||
}
|
||
|
||
concact(expand_ctx, &tok_buffer, right, false);
|
||
i = right_idx;
|
||
continue;
|
||
}
|
||
scc_vec_push(tok_buffer, tok);
|
||
}
|
||
|
||
rescan(expand_ctx, macro, &tok_buffer);
|
||
}
|
||
|
||
static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||
scc_lexer_tok_t next_tok = {0};
|
||
if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == false) {
|
||
SCC_ERROR(*tok_pos, "Unexpected before defined EOF");
|
||
}
|
||
if (next_tok.type == SCC_TOK_L_PAREN) {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
scc_lexer_next_non_blank(expand_ctx->input, &next_tok);
|
||
if (scc_get_tok_subtype(next_tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||
SCC_ERROR(next_tok.loc, "Expected identifier before defined");
|
||
scc_lexer_tok_drop(&next_tok);
|
||
}
|
||
|
||
if (scc_pproc_macro_table_get(expand_ctx->macro_table,
|
||
&next_tok.lexeme) == null) {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
scc_lexer_gen_number_false(&next_tok);
|
||
} else {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
scc_lexer_gen_number_true(&next_tok);
|
||
}
|
||
scc_vec_push(expand_ctx->output, next_tok);
|
||
|
||
if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok)) {
|
||
if (next_tok.type == SCC_TOK_R_PAREN) {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
return false;
|
||
} else {
|
||
SCC_ERROR(next_tok.loc, "Expected ')'");
|
||
scc_lexer_tok_drop(&next_tok);
|
||
}
|
||
}
|
||
} else if (scc_get_tok_subtype(next_tok.type) ==
|
||
SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||
if (scc_pproc_macro_table_get(expand_ctx->macro_table,
|
||
&next_tok.lexeme) == null) {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
scc_lexer_gen_number_false(&next_tok);
|
||
} else {
|
||
scc_lexer_tok_drop(&next_tok);
|
||
scc_lexer_gen_number_true(&next_tok);
|
||
}
|
||
scc_vec_push(expand_ctx->output, next_tok);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||
int ok;
|
||
scc_lexer_tok_t tok;
|
||
while (1) {
|
||
scc_ring_next_consume(*expand_ctx->input, tok, ok);
|
||
if (!ok) {
|
||
return;
|
||
}
|
||
if (scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||
scc_vec_push(expand_ctx->output, tok);
|
||
continue;
|
||
}
|
||
|
||
if (expand_ctx->need_parse_defined &&
|
||
scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) {
|
||
scc_pos_t pos = tok.loc;
|
||
scc_lexer_tok_drop(&tok);
|
||
if (parse_defined(expand_ctx, &pos)) {
|
||
continue;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
// maybe expanded
|
||
scc_pproc_macro_t *macro =
|
||
scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme);
|
||
|
||
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;
|
||
scc_vec_push(expand_ctx->output, tok);
|
||
continue;
|
||
}
|
||
expand_ctx->need_rescan = true;
|
||
|
||
expand_ctx->call_pos = tok.loc;
|
||
if (macro->type == SCC_PP_MACRO_OBJECT) {
|
||
scc_lexer_tok_drop(&tok);
|
||
expand_object_macro(expand_ctx, macro);
|
||
} else if (macro->type == SCC_PP_MACRO_FUNCTION) {
|
||
scc_lexer_tok_t expect_tok;
|
||
scc_ring_peek(*expand_ctx->input, expect_tok, ok);
|
||
if (ok == false || expect_tok.type != SCC_TOK_L_PAREN) {
|
||
scc_vec_push(expand_ctx->output, tok);
|
||
continue;
|
||
}
|
||
|
||
scc_lexer_tok_drop(&tok);
|
||
expand_function_macro(expand_ctx, macro);
|
||
} else {
|
||
UNREACHABLE();
|
||
}
|
||
}
|
||
}
|