#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/precedence.h" int *precedence_symbol; int *precedence_production; struct precedence_def{ int flag; int *list; size_t nlist; } *precedence_defs; size_t nprecedence_defs; void precedence_tables_fill(); void precedence_tables_free(); #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); GET_VARIABLE(precedence_defs, def_handle); GET_VARIABLE(nprecedence_defs, def_handle); precedence_tables_fill(); 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); printf("int *precedence_symbol = (int[]){"); for(size_t i = 0; i < total_symbols; i++) printf("%d, ", precedence_symbol[i]); printf("};\n"); printf("int *precedence_production = (int[]){"); for(size_t i = 0; i < total_productions; i++) printf("%d, ", precedence_production[i]); printf("};\n"); 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(); precedence_tables_free(); util_tables_free(); dlclose(table_handle); dlclose(def_handle); return r; } void precedence_tables_fill() { precedence_symbol = calloc(total_symbols, sizeof(*precedence_symbol)); precedence_production = calloc(total_productions, sizeof(*precedence_production)); for(size_t i = 0; i < nprecedence_defs; i++) for(size_t j = 0; j < precedence_defs[i].nlist; j++) if(precedence_defs[i].flag >= 0) precedence_symbol[precedence_defs[i].list[j]] = PRECEDENCE_SET(precedence_defs[i].flag, i+1); else precedence_production[precedence_defs[i].list[j]] = PRECEDENCE_SET(~precedence_defs[i].flag, i+1); for(size_t i = 0; i < total_productions; i++) { if(precedence_production[i]) continue; for(size_t j = 0; j < grammar[i].nRHS; j++) if(precedence_symbol[grammar[i].RHS[j]]) { precedence_production[i] = precedence_symbol[grammar[i].RHS[j]]; break; } } } void precedence_tables_free() { free(precedence_symbol); free(precedence_production); }