aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2025-07-06 17:35:06 +0300
committerkartofen <mladenovnasko0@gmail.com>2025-07-06 17:35:06 +0300
commitb65dd53885eabb8f39a3115039563edc08efb2b4 (patch)
tree75ec27e5cda989316b2498c913e0283c9ed08841
parent0e0c0e0f26fcd669e45604fd5d9bcc2891a932a2 (diff)
quick and easy semantic actions
-rw-r--r--clr-table.c2
-rw-r--r--demos/generate-parser.c33
-rw-r--r--demos/sample-files/defs.c12
-rw-r--r--demos/sample-files/parser-skeleton.c8
-rw-r--r--lr-parser.c13
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();