@@ -2,11 +2,12 @@
# include <scc_pproc.h>
static scc_lexer_tok_t stringify_argument ( 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 ; // 是否需要插入空格
for ( usize i = 0 ; i < arg_tokens - > size ; i + + ) {
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 ; // 标记遇到空白
@@ -16,7 +17,6 @@ static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
// 需要空格且当前不是第一个有效token, 插入一个空格
if ( need_space & & i > 0 ) {
scc_cstring_append_ch ( & str , ' ' ) ;
need_space = 0 ;
}
// 对字符串/字符常量内的 " 和 \ 进行转义
@@ -36,6 +36,40 @@ static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) {
return result ;
}
static scc_lexer_tok_t concatenate_tokens ( const scc_lexer_tok_t * left ,
const scc_lexer_tok_t * right ) {
Assert ( left ! = null & & right ! = null ) ;
scc_cstring_t new_lex = scc_cstring_create ( ) ;
scc_cstring_append ( & new_lex , & left - > lexeme ) ;
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 ;
int ok ;
scc_ring_next_consume ( * ring , result , ok ) ;
if ( ! ok ) {
scc_lexer_tok_drop ( & result ) ;
return result ;
}
scc_ring_next_consume ( * ring , result , ok ) ;
if ( ok ) {
scc_lexer_tok_drop ( & result ) ;
return result ;
}
scc_lexer_drop_ring ( ring ) ;
scc_lexer_drop ( & lexer ) ;
scc_sstream_drop ( & sstream ) ;
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 ) {
@@ -69,11 +103,13 @@ void scc_pproc_expand_by_src(scc_pproc_t *pp, const scc_pproc_macro_t *macro) {
ctx . macro_table = & pp - > macro_table ;
ctx . need_rescan = false ;
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_marco_table_init ( ctx . expanded_set ) ;
scc_pproc_expand_macro ( & ctx ) ;
pp - > expanded_ring = scc_lexer_array_to_ring ( & ctx . output ) ;
scc_pproc_macro_table_drop ( & ctx . expanded_set ) ;
scc_pproc_macro_table_drop ( ctx . expanded_set ) ;
}
static inline void
@@ -85,17 +121,24 @@ split_arguments(scc_pproc_macro_extened_params_t *splited_params,
scc_lexer_tok_t * raw_arg = & scc_vec_at ( * raw_args , i ) ;
if ( raw_arg - > type = = SCC_TOK_COMMA ) {
scc_lexer_tok_drop ( raw_arg ) ;
if ( scc_vec_size ( arg ) & &
scc_vec_at ( arg , scc_vec_size ( arg ) - 1 ) . type = = SCC_TOK_BLANK ) {
scc_lexer_tok_drop ( & scc_vec_pop ( arg ) ) ;
}
scc_vec_push ( * splited_params , arg ) ;
scc_vec_init ( arg ) ;
} else {
if ( raw_arg - > type = = SCC_TOK_BLANK | |
scc_get_tok_subtype ( raw_arg - > type ) = =
SCC_TOK_SUBTYPE_EMPTYSPACE ) {
if ( scc_vec_size ( arg ) = = 0 & & raw_arg - > type = = SCC_TOK_BLANK ) {
scc_lexer_tok_drop ( raw_arg ) ;
} else {
scc_vec_push ( arg , * raw_arg ) ;
}
scc_vec_push ( arg , * raw_arg ) ;
}
}
if ( scc_vec_size ( arg ) & &
scc_vec_at ( arg , scc_vec_size ( arg ) - 1 ) . type = = SCC_TOK_BLANK ) {
scc_lexer_tok_drop ( & scc_vec_pop ( arg ) ) ;
}
scc_vec_push ( * splited_params , arg ) ;
}
@@ -116,6 +159,7 @@ expand_arguments(scc_pproc_macro_extened_params_t *expanded_params,
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 ) ;
}
}
@@ -133,8 +177,44 @@ expanded_params_free(scc_pproc_macro_extened_params_t *expanded_params) {
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_macro_t * expanded_macro =
scc_pproc_macro_new ( & macro - > name , macro - > type ) ;
if ( expanded_macro = = null ) {
LOG_FATAL ( " Out of memory " ) ;
}
scc_pproc_macro_table_set ( expand_ctx - > expanded_set , expanded_macro ) ;
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 ) ;
scc_pproc_expand_macro ( & rescan_ctx ) ;
scc_ring_free ( ring ) ;
scc_vec_foreach ( rescan_ctx . output , i ) {
scc_vec_push ( expand_ctx - > output , scc_vec_at ( rescan_ctx . output , i ) ) ;
}
scc_pproc_macro_table_remove ( expand_ctx - > expanded_set , & macro - > name ) ;
}
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 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 ) ;
@@ -151,62 +231,168 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
// replace
scc_vec_foreach ( macro - > replaces , i ) {
scc_lexer_tok_t tok = scc_vec_at ( macro - > replaces , i ) ;
scc_lexer_tok_t prev_tok = { 0 } ;
if ( i > = 1 ) {
prev_tok = scc_vec_at ( macro - > replaces , i - 1 ) ;
}
scc_lexer_tok_t tok =
scc_lexer_tok_copy ( & scc_vec_at ( macro - > replaces , i ) ) ;
if ( tok . type = = SCC_TOK_BLANK ) {
scc_cstring_free ( & tok . lexeme ) ;
tok . lexeme = scc_cstring_from_cstr ( " " ) ;
scc_vec_push ( expand_ctx - > output , tok ) ;
scc_vec_push ( tok_buffer , tok ) ;
continue ;
}
scc_vec_foreach ( macro - > params , j ) {
if ( scc_cstring_cmp ( & tok . lexeme ,
& ( scc_vec_at ( macro - > params , j ) . lexeme ) ) = = 0 ) {
if ( j > = scc_vec_size ( expanded_params ) ) {
LOG_ERROR ( " Invalid macro parameter " ) ;
goto CONTINUE ;
}
if ( prev_ tok. type = = SCC_TOK_SHARP ) {
// # stringify
scc_lexer_tok_t out =
stringify_argument ( & scc_vec_at ( splited_params , j ) ) ;
scc_vec_pop ( expand_ctx - > output ) ;
scc_vec_push ( expand_ctx - > output , out ) ;
} else {
scc_lexer_tok_vec_t expanded_param =
scc_vec_at ( expanded_params , j ) ;
scc_vec_foreach ( expanded_param , k ) {
tok = scc_vec_at ( expanded_param , k ) ;
tok . lexeme = scc_cstring_copy ( & tok . lexeme ) ;
scc_vec_push ( expand_ctx - > output , tok ) ;
}
if ( tok . type = = SCC_TOK_SHARP ) {
// # stringify
scc_lexer_tok_drop ( & tok ) ;
int right_idx = i + 1 ;
while ( right_idx < ( int ) macro - > replaces . size & &
scc_vec_at ( macro - > replaces , right_idx ) . type = =
SCC_TOK_BLANK ) {
right_idx + + ;
}
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 ( & 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
// 向左扫描找到上一个非空白 token
scc_lexer_tok_drop ( & tok ) ;
int left_idx = i - 1 ;
while ( left_idx > = 0 & &
scc_vec_at ( macro - > replaces , left_idx ) . type = =
SCC_TOK_BLANK ) {
left_idx - - ;
}
// 向右扫描找到下一个非空白 token
int right_idx = i + 1 ;
while ( right_idx < ( int ) macro - > replaces . size & &
scc_vec_at ( macro - > replaces , right_idx ) . type = =
SCC_TOK_BLANK ) {
right_idx + + ;
}
if ( left_idx < 0 | | right_idx > = ( int ) macro - > replaces . size ) {
LOG_FATAL ( " Invalid ## operator " ) ;
}
while ( i + + < right_idx ) {
scc_lexer_tok_drop ( & scc_vec_pop ( tok_buffer ) ) ;
}
int j ;
j = find_params ( & scc_vec_at ( macro - > replaces , left_idx ) , macro ) ;
Assert ( j ! = - 1 & & j < ( int ) scc_vec_size ( splited_params ) ) ;
scc_lexer_tok_vec_t left_vec = scc_vec_at ( splited_params , j ) ;
j = find_params ( & scc_vec_at ( macro - > replaces , right_idx ) , macro ) ;
Assert ( j ! = - 1 & & j < ( int ) scc_vec_size ( splited_params ) ) ;
scc_lexer_tok_vec_t right_vec = scc_vec_at ( splited_params , j ) ;
scc_lexer_tok_t * left =
scc_vec_size ( left_vec )
? & scc_vec_at ( left_vec , scc_vec_size ( left_vec ) - 1 )
: null ;
scc_lexer_tok_t * right =
scc_vec_size ( right_vec ) ? & scc_vec_at ( right_vec , 0 ) : null ;
scc_vec_foreach ( left_vec , k ) {
if ( k + 1 > = scc_vec_size ( left_vec ) ) {
continue ;
}
goto CONTINUE ;
scc_lexer_tok_t tok =
scc_lexer_tok_copy ( & scc_vec_at ( left_vec , k ) ) ;
scc_vec_push ( tok_buffer , tok ) ;
}
scc_lexer_tok_t concate_tok = concatenate_tokens ( left , right ) ;
if ( concate_tok . type = = SCC_TOK_UNKNOWN ) {
LOG_FATAL ( " Invalid ## token " ) ;
}
scc_vec_push ( tok_buffer , concate_tok ) ;
scc_vec_foreach ( right_vec , k ) {
if ( k = = 0 ) {
continue ;
}
scc_lexer_tok_t tok =
scc_lexer_tok_copy ( & scc_vec_at ( right_vec , k ) ) ;
scc_vec_push ( tok_buffer , tok ) ;
}
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 ;
}
}
tok . lexeme = scc_cstring_copy ( & tok. lexeme ) ;
scc_vec_push ( expand_ctx - > output , tok ) ;
CONTINUE :
continue ;
scc_vec_push ( tok_buffer , tok ) ;
}
expanded_params_free ( & splited_params ) ;
expanded_params_free ( & expanded_params ) ;
rescan ( expand_ctx , macro , & tok_buffer ) ;
}
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_vec_at ( macro - > replaces , i ) ;
scc_lexer_tok_t tok =
scc_lexer_tok_copy ( & scc_vec_at ( macro - > replaces , i ) ) ;
if ( tok . type = = SCC_TOK_BLANK ) {
scc_cstring_free ( & tok . lexeme ) ;
tok . lexeme = scc_cstring_from_cstr ( " " ) ;
} else {
tok . lexeme = scc_cstring_copy ( & tok . lexeme ) ;
} else if ( tok . type = = SCC_TOK_SHARP_SHARP ) {
// ## contact
// 向左扫描找到上一个非空白 token
int left_idx = i - 1 ;
while ( left_idx > = 0 & &
scc_vec_at ( macro - > replaces , left_idx ) . type = =
SCC_TOK_BLANK ) {
left_idx - - ;
}
// 向右扫描找到下一个非空白 token
int right_idx = i + 1 ;
while ( right_idx < ( int ) macro - > replaces . size & &
scc_vec_at ( macro - > replaces , right_idx ) . type = =
SCC_TOK_BLANK ) {
right_idx + + ;
}
if ( left_idx < 0 | | right_idx > = ( int ) macro - > replaces . size ) {
LOG_FATAL ( " Invalid ## operator " ) ;
}
scc_lexer_tok_t * left = & scc_vec_at ( macro - > replaces , left_idx ) ;
scc_lexer_tok_t * right = & scc_vec_at ( macro - > replaces , right_idx ) ;
scc_lexer_tok_t concate_tok = concatenate_tokens ( left , right ) ;
while ( i + + < right_idx ) {
scc_lexer_tok_drop ( & scc_vec_pop ( tok_buffer ) ) ;
}
if ( concate_tok . type = = SCC_TOK_UNKNOWN ) {
LOG_FATAL ( " Invalid ## token " ) ;
}
scc_vec_push ( tok_buffer , concate_tok ) ;
i = right_idx ;
continue ;
}
scc_vec_push ( expand_ctx - > output , tok ) ;
scc_vec_push ( tok_buffer , tok ) ;
}
rescan ( expand_ctx , macro , & tok_buffer ) ;
}
void scc_pproc_expand_macro ( scc_pproc_expand_t * expand_ctx ) {
@@ -225,30 +411,27 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
scc_pproc_macro_t * macro =
scc_pproc_macro_table_get ( expand_ctx - > macro_table , & tok . lexeme ) ;
if ( macro = = null | | scc_pproc_macro_table_get (
& expand_ctx - > expanded_set , & macro - > name ) ) {
if ( macro = = null | |
scc_pproc_macro_table_get ( expand_ctx - > expanded_set , & macro - > name ) ) {
scc_vec_push ( expand_ctx - > output , tok ) ;
continue ;
}
expand_ctx - > need_rescan = true ;
scc_pproc_macro_t * expanded_macro =
scc_pproc_macro_new ( & macro - > name , macro - > type ) ;
if ( expanded_macro = = null ) {
LOG_FATAL ( " Out of memory " ) ;
}
scc_pproc_macro_table_set ( & expand_ctx - > expanded_set , expanded_macro ) ;
if ( macro - > type = = SCC_PP_MACRO_OBJECT ) {
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 ;
}
expand_function_macro ( expand_ctx , macro ) ;
} else {
UNREACHABLE ( ) ;
}
RESCAN :
scc_pproc_macro_table_remove ( & expand_ctx - > expanded_set , & macro - > name ) ;
// TODO expand # and ##
continue ;
}
if ( expand_ctx - > need_rescan ) {
expand_ctx - > need_rescan = false ;