diff options
author | kartofen <mladenovnasko0@gmail.com> | 2025-07-06 17:35:06 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2025-07-06 17:35:06 +0300 |
commit | b65dd53885eabb8f39a3115039563edc08efb2b4 (patch) | |
tree | 75ec27e5cda989316b2498c913e0283c9ed08841 | |
parent | 0e0c0e0f26fcd669e45604fd5d9bcc2891a932a2 (diff) |
quick and easy semantic actions
-rw-r--r-- | clr-table.c | 2 | ||||
-rw-r--r-- | demos/generate-parser.c | 33 | ||||
-rw-r--r-- | demos/sample-files/defs.c | 12 | ||||
-rw-r--r-- | demos/sample-files/parser-skeleton.c | 8 | ||||
-rw-r--r-- | lr-parser.c | 13 |
5 files changed, 56 insertions, 12 deletions
diff --git a/clr-table.c b/clr-table.c index 23345ec..fb68826 100644 --- a/clr-table.c +++ b/clr-table.c @@ -68,7 +68,7 @@ static void itemset_print(struct item *set, size_t nset) static size_t itemset_handle(struct item *set, size_t nset) { #ifdef _LAZY_LALR - int use_state = SIZE_MAX; + size_t use_state = SIZE_MAX; #endif // 1. is set in seen_sets diff --git a/demos/generate-parser.c b/demos/generate-parser.c index 8d50ad6..d32a697 100644 --- a/demos/generate-parser.c +++ b/demos/generate-parser.c @@ -14,6 +14,8 @@ int (*symbol_is_valid)(symbol s); struct production *grammar; size_t total_productions; +char **semantic_action_str; + #include "util-tables.c" #define _LAZY_LALR @@ -35,19 +37,21 @@ void *xdlsym(void *handle, char *sym) int main(int argc, char **argv) { if(argc != 2) return 1; - + void *handle = dlopen(argv[1], RTLD_LAZY); if(!handle) { puts(dlerror()); return 1; } - GET_VARIABLE(total_symbols, handle); + GET_VARIABLE(total_symbols, handle); GET_VARIABLE(symbol_is_terminal, handle); GET_VARIABLE(symbol_is_input_end, handle); GET_VARIABLE(symbol_is_valid, handle); GET_VARIABLE(grammar, handle); GET_VARIABLE(total_productions, handle); + GET_VARIABLE(semantic_action_str, handle); + util_tables_fill(); table_fill() && (fprintf(stderr, "ERROR: Table couldn't be generated\n"), exit(1), 1); - + printf("size_t total_symbols = %zu;\n", total_symbols); printf("IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s), {return s < total_symbols;})\n"); @@ -57,15 +61,32 @@ int main(int argc, char **argv) printf("struct production *grammar = _grammar;"); printf("size_t total_productions = %zu;\n", total_productions); - - printf("struct action **table = (struct action *([])){\n", table_states, total_symbols); + + 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*%d+3*n-1))\n", grammar[i].nRHS-1); + printf("int __prod%d_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%d_action, ", i); + printf("};"); + table_free(); util_tables_free(); - + dlclose(handle); return 0; } diff --git a/demos/sample-files/defs.c b/demos/sample-files/defs.c index 92d6837..76a0534 100644 --- a/demos/sample-files/defs.c +++ b/demos/sample-files/defs.c @@ -35,3 +35,15 @@ static struct production _grammar[] = { struct production *grammar = _grammar; size_t total_productions = sizeof(_grammar)/sizeof(*_grammar); + +// #include "???.h" +char **semantic_action_str = (char *([])){ + "v = A(0);", + "v = A(0) + A(2);", + "v = A(0) - A(2);", + "v = A(0);", + "v = A(1);", + "v = A(0);", + "v = 0;", + "v = 1;", +}; diff --git a/demos/sample-files/parser-skeleton.c b/demos/sample-files/parser-skeleton.c index 031d829..f601369 100644 --- a/demos/sample-files/parser-skeleton.c +++ b/demos/sample-files/parser-skeleton.c @@ -41,10 +41,12 @@ int main(int argc, char **argv) { if(argc != 2) { fprintf(stderr, "ERROR: Not enough arguments\n"); - return 1; + return 1; } input = argv[1]; - - return lr_parser(); + + printf("INPUT: '%s'\n", input); + printf("OUTPUT: %d\n", lr_parser()); + return 0; } diff --git a/lr-parser.c b/lr-parser.c index 3ab9af4..f7197c5 100644 --- a/lr-parser.c +++ b/lr-parser.c @@ -9,6 +9,9 @@ #include "parts/grammar.h" #include "parts/table.h" #include "parts/toklist.h" +// and +typedef int (*semantic_action_fn)(int *stack_head); +extern semantic_action_fn *semantic_actions; typedef int stack_item; @@ -32,10 +35,12 @@ int lr_parser() switch(a.type) { case ACTION_SHIFT: push(eat()); + push(-10000000); // the semantic action push(a.arg); break; case ACTION_REDUCE: - for(size_t i = 0; i < 2*grammar[a.arg].nRHS; i++) pop(); + int semantic_value = semantic_actions[a.arg](stack_head); + for(size_t i = 0; i < 3*grammar[a.arg].nRHS; i++) pop(); symbol lhs = grammar[a.arg].LHS; struct action a_goto = table[(size_t)*stack_head][lhs]; @@ -47,10 +52,11 @@ int lr_parser() } push(lhs); + push(semantic_value); push(a_goto.arg); break; case ACTION_ACCEPT: - return 0; + return *(stack_head-1); case ACTION_NOT_SET: default: fprintf(stderr, @@ -124,6 +130,9 @@ static symbol *tok = toklist; symbol toklist_eat() { return *(tok++); } // unsafe symbol toklist_peek() { return *tok; } // unsafe +int none(int *stack_head) {(void)stack_head; return 0;}; +semantic_action_fn *semantic_actions = (semantic_action_fn[]){none, none, none, none, none, none, none, none}; + int main(void) { return lr_parser(); |