#include #include #include #include #include // getopt #include #define DEFUALT_PATH "./bin" #define DEFUALT_TYPE "lalr-table" #define DEFAULT_OUTPUT "bin/a" #include "parts/symbol.h" size_t total_symbols; int (*symbol_is_terminal)(symbol s); int (*symbol_is_input_end)(symbol s); int (*symbol_is_valid)(symbol s); #include "parts/grammar.h" struct production *grammar; size_t total_productions; char **semantic_action_str; #include "parts/table.h" struct action **table; size_t table_states; int (*table_fill)(); void (*table_free)(); #include "util-tables.c" void *xdlsym(void *handle, char *sym) { void *r = dlsym(handle, sym); if(!r) { fprintf(stderr, "ERROR: Symbol '%s' was not found\n", sym); dlclose(handle); exit(1); } return r; } #define GET_VARIABLE(var, handle) \ var = *(typeof(&var))xdlsym(handle, #var) char *modpath(char *name) { static char fullpath[128]; // TODO: search the GENERATE_PARSER_PATH env var char *path = DEFUALT_PATH; assert(snprintf(fullpath, 128, "%s/%s.so", path, name) < 128); return fullpath; } char *add_extension(char *str, char *ext) { static char full[128]; assert((strlen(str) + strlen(ext) + 1) <= 128); memcpy(full, str, strlen(str)+1); return strcat(full, ext); } void set_stdout(char *filename) { if(!filename) filename = "/dev/tty"; assert(freopen(filename, "w", stdout)); } int main(int argc, char **argv) { char *type = DEFUALT_TYPE; char *output_path = DEFAULT_OUTPUT; int opt; while((opt = getopt(argc, argv, "t:o:")) != -1) { switch(opt) { case 't': type = optarg; break; case 'o': output_path = optarg; break; default: fprintf(stderr, "ERROR: Unknown options '%c'\n", optopt); return 1; } } if(optind == argc) { fprintf(stderr, "ERROR: No input file\n"); return 1; } void *table_handle = dlopen(modpath(type), RTLD_LAZY); if(!table_handle) { fputs(dlerror(), stderr); return 1; } void *def_handle = dlopen(argv[optind], RTLD_LAZY); if(!def_handle) { fputs(dlerror(), stderr); return 1; } GET_VARIABLE(table, table_handle); GET_VARIABLE(table_states, table_handle); GET_VARIABLE(table_fill, table_handle); GET_VARIABLE(table_free, table_handle); GET_VARIABLE(total_symbols, def_handle); GET_VARIABLE(symbol_is_terminal, def_handle); GET_VARIABLE(symbol_is_input_end, def_handle); GET_VARIABLE(symbol_is_valid, def_handle); GET_VARIABLE(grammar, def_handle); GET_VARIABLE(total_productions, def_handle); GET_VARIABLE(semantic_action_str, def_handle); util_tables_fill(); int r = 0; if((r = table_fill())) { fprintf(stderr, "ERROR: Table couldn't be generated\n"); goto cleanup; } set_stdout(add_extension(output_path, ".c")); printf("size_t total_symbols = %zu;\n", total_symbols); printf("IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s)) {return s < total_symbols;}\n"); printf("struct production _grammar[] = {\n"); grammar_print_cstyle(); printf("};\n"); printf("struct production *grammar = _grammar;"); printf("size_t total_productions = %zu;\n", total_productions); printf("struct action **table = (struct action *([])){\n"); table_print_cstyle(); printf("};\n"); printf("size_t table_states = %zu;\n", table_states); for(size_t i = 0; i < total_productions; i++) { printf("#define A(n) (*(stack_head-3*%zu+3*n-1))\n", grammar[i].nRHS-1); printf("int __prod%zu_action(int *stack_head)\n", i); printf("{ int v;\n"); printf(semantic_action_str[i]); printf("return v; }\n"); printf("#undef A\n"); } printf("typedef int (*semantic_action_fn)(int *stack_head);\n"); printf("semantic_action_fn *semantic_actions = (semantic_action_fn[]){\n"); for(size_t i = 0; i < total_productions; i++) printf("__prod%zu_action, ", i); printf("};"); set_stdout(NULL); cleanup: table_free(); util_tables_free(); dlclose(table_handle); dlclose(def_handle); return r; }