#include #include #define STR_SIZE_LIMIT 65536 #define IMP #define WANT_BUILD #define WANT_CSTR #define WANT_STR #define WANT_TOKENIZER #define WANT_DYN_ARR #define WANT_PATH #define WANT_ENV #include "./src/lib.h" #include #include bool tkn_expect(struct tokenizer *tkn, enum token_type type, struct token *out_tk, enum err *out_err); bool tkn_expect_id(struct tokenizer *tkn, const char *cstr, struct token *out_tk, enum err *out_err); bool tkn_parse_function(struct tokenizer *tkn); bool run_function(struct str str); bool tkn_parse_pp_directive(struct tokenizer *tkn, struct token *out_tk, enum err *out_err); enum c_token_type { _TT = TK_LAST, TK_PP_DEF, TK_PP_INC }; struct token_pp_inc { enum c_token_type type; u64 loc_start; u64 loc_end; struct str string; }; struct token_pp_def { enum token_type type; u64 loc_start; u64 loc_end; struct str name; struct str val; }; bool skip_token(struct tokenizer *tkn, char c); int main(int argc, char *argv[]) { enum err err = ERR_OK; struct path src_path = {0}; struct file f = {0}; struct str code = {0}; struct tokenizer tkn = {0}; struct tokenizer_options tkn_opts = {0}; struct token tk = {0}; struct dyn_arr tk_da = {0}; tk_da = dyn_arr_create(sizeof(struct token), &err); src_path = path_from_cstr_ns("./first.c", &err); f = path_file_read_all(&src_path, &err); code = str_from_cstr((char*)f.data, f.size, &err); tkn_opts.skip_token = skip_token; tkn = tokenizer_create(code, src_path, &tkn_opts, &err); tkn.edata = &tk_da; tk = tokenizer_next_token(&tkn, &err); do { if ( err != ERR_OK ) { fprintf(stderr, "ERROR: Failed tokenizing `%.*s`: %s\n", (int) src_path.size, src_path.data, err_to_name[err]); goto error_exit; } switch ( tk.type ) { case TK_POUND: if ( ! tkn_parse_pp_directive(&tkn, NULL, &err) ) goto error_exit; break; case TK_NL: break; default: fprintf(stderr, "%s ERROR: Invalid Token `%s`\n", tokenizer_token_loc_temp(&tkn, &tk, TLF_VIM, NULL), token_to_cstr(tk.type)); goto error_exit; } tk = tokenizer_next_token(&tkn, &err); } while ( tk.type != TK_EOF ); /* if ( ! tkn_expect(&tkn, TK_POUND) ) return 1; if ( ! tkn_expect_id(&tkn, "run") ) return 1; if ( ! tkn_expect(&tkn, TK_L_CUR_BRACES) ) return 1; if ( ! tkn_parse_function(&tkn) ) return 1; if ( ! tkn_expect(&tkn, TK_R_CUR_BRACES) ) return 1; if ( ! tkn_expect(&tkn, TK_EOF) ) return 1; */ printf("%s\n", err_to_name[err]); error_exit: if ( f.data != NULL ) free(f.data); if ( tk_da.data != NULL ) dyn_arr_destroy(&tk_da, NULL); (void) argc; (void) argv; return 0; } bool skip_token(struct tokenizer *tkn, char c) { UNUSED(tkn); return (c == ' ') || (c == '\r') || (c == '\t'); } bool tkn_expect(struct tokenizer *tkn, enum token_type type, struct token *out_tk, enum err *out_err) { enum err err = ERR_OK; enum err *perr = &err; LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false); if ( tokenizer_is_next(tkn, type, out_tk, perr) == false ) { struct token tk = {0}; tk = tokenizer_next_token(tkn, perr); if ( err != ERR_OK ) { fprintf(stderr, "Failed to get next token: %s\n", err_to_name[err]); return false; } fprintf(stderr, "%s ERRRO: Got wrong token, expected: %s, got: %s\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), token_to_cstr(type), token_to_cstr(tk.type)); return false; } return true; } bool tkn_expect_id(struct tokenizer *tkn, const char *cstr, struct token *out_tk, enum err *out_err) { enum err err = ERR_OK; struct str str = {0}; LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false); LIB_ARG_MUST_NOT_BE_NULL(cstr, out_err, false); str = str_from_cstr_ns(cstr, &err); if ( tokenizer_is_next_id(tkn, str, out_tk, &err) == false ) { struct token tk = {0}; struct token_wstr *tk_ws = NULL; tk = tokenizer_next_token(tkn, &err); if ( err != ERR_OK ) { fprintf(stderr, "Failed to get next token: %s\n", err_to_name[err]); return false; } if ( tk.type != TK_ID ) { fprintf(stderr, "%s ERROR: Got wrong token, expected: TK_ID, got: %s\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), token_to_cstr(tk.type)); return false; } tk_ws = (struct token_wstr *)&tk; fprintf(stderr, "%s ERROR: Got wrong id, expected: %s, got: %.*s\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), cstr, (int) tk_ws->string.size, tk_ws->string.data); return false; } return true; } bool tkn_parse_pp_directive(struct tokenizer *tkn, struct token *out_tk, enum err *out_err) { static char buf[1024] = {0}; static char buf2[1024] = {0}; struct token tk = {0}; struct token_wstr *tk_ws = NULL; enum err err = ERR_OK; enum err *perr = &err; LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false); LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, false); if ( out_err != NULL ) { perr = out_err; } tk = tokenizer_next_token(tkn, perr); if ( *perr != ERR_OK ) { fprintf(stderr, "Failed to get next token: %s\n", err_to_name[*perr]); return false; } if ( tk.type != TK_ID ) { fprintf(stderr, "%s Got wrong token, expected: TK_ID, got: %s\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), token_to_cstr(tk.type)); return false; } tk_ws = (struct token_wstr *) &tk; if ( str_eq_cstr(tk_ws->string, "define", 6) == true ) { struct token_pp_def tk_def = {0}; if ( ! tkn_expect(tkn, TK_ID, &tk, perr) ) return false; tk_ws = (struct token_wstr *) &tk; tk_def.loc_start = tk_ws->loc_start; memcpy(buf, tk_ws->string.data, tk_ws->string.size); tk_def.name.data = buf; tk_def.name.size = tk_ws->string.size; tk = tokenizer_next_token(tkn, &err); if ( err != ERR_OK ) { fprintf(stderr, "Failed to get next token: %s\n", err_to_name[err]); return false; } switch ( tk.type ) { case TK_ID: case TK_STR_LIT: case TK_NUM_LIT: tk_ws = (struct token_wstr *) &tk; break; default: fprintf(stderr, "%s Got wrong token, expected:" " TK_ID/TK_STR_LIT/TK_NUM_LIT, got: %s\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), token_to_cstr(tk.type)); return false; } memcpy(buf2, tk_ws->string.data, tk_ws->string.size); tk_def.val.data = buf2; tk_def.val.size = tk_ws->string.size; tk_def.loc_end = tk_ws->loc_end; if ( ! tkn_expect(tkn, TK_NL, NULL, perr) ) return false; LIB_SET_IF_NOT_NULL(out_tk, *(struct token *) &tk_def); return true; } if ( str_eq_cstr(tk_ws->string, "include", 7) == true ) { struct token_pp_inc tk_inc = {0}; tk_inc.type = TK_PP_INC; if ( ! tkn_expect(tkn, TK_L_ANG_BRACKET, NULL, perr) ) return false; if ( ! tkn_expect(tkn, TK_ID, &tk, perr) ) return false; tk_ws = (struct token_wstr *) &tk; tk_inc.loc_start = tk_ws->loc_start; tk_inc.loc_end = tk_ws->loc_end; tk_inc.string.data = buf; tk_inc.string.size = tk_ws->string.size; memcpy(buf, tk_ws->string.data, tk_ws->string.size); if ( ! tkn_expect(tkn, TK_DOT, NULL, perr) ) return false; if ( ! tkn_expect_id(tkn, "h", NULL, perr) ) return false; if ( ! tkn_expect(tkn, TK_R_ANG_BRACKET, NULL, perr) ) return false; if ( ! tkn_expect(tkn, TK_NL, NULL, perr) ) return false; LIB_SET_IF_NOT_NULL(out_tk, *(struct token *) &tk_inc); return true; } if ( str_eq_cstr(tk_ws->string, "if", 2) == true ) { return true; } if ( str_eq_cstr(tk_ws->string, "ifdef", 2) == true ) { return true; } if ( str_eq_cstr(tk_ws->string, "ifndef", 2) == true ) { return true; } /* Format src.c:line:col: msg */ fprintf(stderr, "%s ERROR: Invalid Pre-Compiler directive `%.*s`\n", tokenizer_token_loc_temp(tkn, &tk, TLF_VIM, NULL), (int) tk_ws->string.size, tk_ws->string.data); return false; } /* int main(void) { enum err err = ERR_OK; bool was_rebuild = false; struct dyn_arr dirs = {0}; size_t i = 0; was_rebuild = build_go_rebuild_yourself(__FILE__, &err); if ( was_rebuild == true ) { return 0; } dirs = dir_list_with_ext("./src", ".c", &err); free(dirs); return 0; } */