%top{ #define _GNU_SOURCE } %{ #include #include #include #include kvec_t(char *) query; static sds buffer; static sds query_string_buffer; #define ECHOC(x) do { buffer = sdscatlen(buffer, &x, 1); } while(0) #define ECHOS(x) do { buffer = sdscat(buffer, x); } while(0) extern char * expand_c_query(void); %} identifier [a-zA-z][a-zA-z0-9_]* %x IN_COMMENT IN_MULTILINE_COMMENT IN_STRING %x IN_QUERY IN_QUERY_STRING %option nodefault %option noyywrap %option nounput noinput %option prefix="tbsp_c_" %% \/\/ { ECHOS(yytext); BEGIN IN_COMMENT; } \/\* { ECHOS(yytext); BEGIN IN_COMMENT; } \" { ECHOS(yytext); BEGIN IN_STRING; } \$\$ { BEGIN IN_QUERY; } .|\n { ECHOS(yytext); } { \n { ECHOS(yytext); BEGIN INITIAL; } . { ECHOS(yytext); } } { \*\/ { ECHOS(yytext); BEGIN INITIAL; } . { ECHOS(yytext); } } { \\\" { ECHOS(yytext); } \" { ECHOS(yytext); BEGIN INITIAL; } . { ECHOS(yytext); } } { \-\> { ; } {identifier} { kv_push(char *, query, strdup(yytext)); } \" { sdsfree(query_string_buffer); query_string_buffer = sdsnew(yytext); BEGIN IN_QUERY_STRING; } . { char * expanded_query = expand_c_query(); ECHOS(expanded_query); free(expanded_query); query.n = 0; ECHOS(yytext); BEGIN INITIAL; } } { \" { query_string_buffer = sdscat(query_string_buffer, yytext); kv_push(char *, query, strdup(query_string_buffer)); BEGIN IN_QUERY; } . { query_string_buffer = sdscat(query_string_buffer, yytext); } } %% char * tbsp_c_expland_code(const char * const s) { YY_BUFFER_STATE const b = yy_scan_string(s); tbsp_c_lex(); tbsp_c__delete_buffer(b); return buffer; } char * expand_c_query(void) { const char * const query_fmt = "tbnode_child_by_field_name(%s, %s)"; char * r; r = strdup("tbnode"); for (int i = 0; i < kv_size(query); i++) { char * old = r; int ignore = asprintf(&r, query_fmt, r, kv_A(query, i)); (void)ignore; free(old); } return r; } int tbsp_c_yy_init(void) { kv_init(query); buffer = sdsnew(""); query_string_buffer = sdsnew(""); return 0; } int tbsp_c_yy_reset(void) { sdsclear(buffer); sdsclear(query_string_buffer); return 0; } int tbsp_c_yy_deinit(void) { tbsp_c__delete_buffer(YY_CURRENT_BUFFER); sdsfree(buffer); sdsfree(query_string_buffer); return 0; }