aboutsummaryrefslogtreecommitdiff
path: root/lr-parser.c
diff options
context:
space:
mode:
authorkartofen <kartofen.mail.0@protonmail.com>2025-09-24 00:06:54 +0300
committerkartofen <kartofen.mail.0@protonmail.com>2025-09-24 00:06:54 +0300
commitfec8e3a95becfb3dc2a3eb0f512a120a7a4551c5 (patch)
tree8d3da9f0c3fa36f5e06bc49cc1bfdc0db3099ea1 /lr-parser.c
parentdb1b9c8dcb0d115217a33c2fe8e0760d49143e11 (diff)
debug info through the lr parser
Diffstat (limited to 'lr-parser.c')
-rw-r--r--lr-parser.c73
1 files changed, 41 insertions, 32 deletions
diff --git a/lr-parser.c b/lr-parser.c
index a909f7f..68b874a 100644
--- a/lr-parser.c
+++ b/lr-parser.c
@@ -12,14 +12,15 @@
#include "parts/table.h"
#include "parts/toklist.h"
// and
-typedef stack_item (*semantic_action_fn)(stack_item *item_head);
+typedef void *(*semantic_action_fn)(stack_item *, stack_item *);
extern semantic_action_fn *semantic_actions;
-#define STACK_CAP 128
+#define ARR_LEN(arr) (sizeof(arr)/sizeof(*arr))
+#define STACK_CAP 64
static stack_item item_bottom[STACK_CAP];
static stack_item *item_head = item_bottom;
-static int state_bottom[STACK_CAP];
+static int state_bottom[STACK_CAP*2];
static int *state_head = state_bottom;
static void print_stack()
@@ -30,38 +31,36 @@ static void print_stack()
fprintf(stderr, "}\n\n");
}
-struct lr_errinfo {
- enum lr_errtype { LR_ERR_STACKCAP_EXCEEDED, LR_ERR_UNEXPECTED_SYMBOL, LR_ERR_NO_GOTO_ENTRY } type;
+struct lr_parseinfo {
+ enum { LR_SUCCESS = 0, LR_ABORTED, LR_ERR_STACKCAP_EXCEEDED, LR_ERR_UNEXPECTED_SYMBOL, LR_ERR_NO_GOTO_ENTRY } type;
union {
size_t stack_cap;
struct { symbol sym; size_t state; } idx;
};
};
-struct lr_errinfo *lr_parser(void *value)
+void *lr_parser(struct lr_parseinfo *parseinfo)
{
- static struct lr_errinfo errinfo;
+ void *semantic_action_r;
+ stack_item semantic_value;
#define push(stack_head, stack_bottom, item) do { \
- if(++stack_head - stack_bottom < STACK_CAP ) *stack_head = item; \
- else { errinfo = (struct lr_errinfo){.type = LR_ERR_STACKCAP_EXCEEDED, .stack_cap = STACK_CAP }; return &errinfo; } \
+ if((size_t)(++stack_head - stack_bottom) < (size_t)ARR_LEN(stack_bottom) ) *stack_head = item; \
+ else { *parseinfo = (struct lr_parseinfo){.type = LR_ERR_STACKCAP_EXCEEDED, .stack_cap = STACK_CAP }; return NULL; } \
} while(0)
-#define pop(stack_head) (--stack_head)
+#define pop(stack_head, stack_bottom) if(--stack_head < stack_bottom) exit(33);
#define spush(item) push(state_head, state_bottom, item)
-#define spop() pop(state_head)
+#define spop() pop(state_head, state_bottom)
#define ipush(item) push(item_head, item_bottom, item)
-#define ipop() pop(item_head)
-
-#define eat() toklist_eat()
-#define peek() toklist_peek()
+#define ipop() pop(item_head, item_bottom)
while(1) {
- struct action a = table[(size_t)*state_head][token_sym(peek())];
+ struct action a = table[(size_t)*state_head][token_sym(toklist_peek())];
switch(a.type) {
case ACTION_SHIFT:;
- struct token *t = eat();
+ struct token *t = toklist_eat();
ipush(*(stack_item*)token_val(t));
spush(token_sym(t));
@@ -71,8 +70,9 @@ struct lr_errinfo *lr_parser(void *value)
print_stack();
#endif
break;
- case ACTION_REDUCE:
- stack_item semantic_value = semantic_actions[a.arg](item_head);
+ case ACTION_REDUCE:;
+ if((semantic_action_r = semantic_actions[a.arg](&semantic_value, item_head))) goto abort;
+
for(size_t i = 0; i < grammar[a.arg].nRHS; i++) {
ipop(); spop(); spop();
}
@@ -80,8 +80,8 @@ struct lr_errinfo *lr_parser(void *value)
symbol lhs = grammar[a.arg].LHS;
struct action a_goto = table[(size_t)*state_head][lhs];
if(a_goto.type != ACTION_GOTO) {
- errinfo = (struct lr_errinfo){.type = LR_ERR_NO_GOTO_ENTRY, .idx = {lhs, (size_t)*state_head}};
- return &errinfo;
+ *parseinfo = (struct lr_parseinfo){.type = LR_ERR_NO_GOTO_ENTRY, .idx = {lhs, (size_t)*state_head}};
+ return NULL;
}
ipush(semantic_value);
@@ -95,32 +95,41 @@ struct lr_errinfo *lr_parser(void *value)
case ACTION_ACCEPT:
ipush((stack_item){0});
spush(0); spush(0);
- // todo: better fix for reducing the final production expecting an END_INPUT on the stack
- *(stack_item *)value = semantic_actions[0](item_head);
- return NULL;
+
+ // todo: better fix for reducing the final production expecting an END_INPUT on the stack
+ if((semantic_action_r = semantic_actions[0](&semantic_value, item_head))) goto abort;
+
+ ipush(semantic_value);
+ parseinfo->type = LR_SUCCESS;
+ return item_head;
case ACTION_NOT_SET:
default:
- errinfo = (struct lr_errinfo){.type = LR_ERR_UNEXPECTED_SYMBOL, .idx = {token_sym(peek()), (size_t)*state_head}};
- return &errinfo;
+ *parseinfo = (struct lr_parseinfo){.type = LR_ERR_UNEXPECTED_SYMBOL, .idx = {token_sym(toklist_peek()), (size_t)*state_head}};
+ return NULL;
}
}
+
+abort:
+ parseinfo->type = LR_ABORTED;
+ return semantic_action_r;
}
-char *lr_err_str(struct lr_errinfo *errinfo)
+char *lr_err_str(struct lr_parseinfo *parseinfo)
{
// TODO: check if strbuf cap is exceeded
static char strbuf[128];
- switch(errinfo->type) {
+ switch(parseinfo->type) {
case LR_ERR_STACKCAP_EXCEEDED:
- snprintf(strbuf, sizeof(strbuf), "LR parser stack capacity of %zu has been exceeded", errinfo->stack_cap);
+ snprintf(strbuf, sizeof(strbuf), "LR parser stack capacity of %zu has been exceeded", parseinfo->stack_cap);
break;
case LR_ERR_UNEXPECTED_SYMBOL:
- snprintf(strbuf, sizeof(strbuf), "Unexpected symbol '%s' at state '%zu'", symbol_to_str[errinfo->idx.sym], errinfo->idx.state);
+ snprintf(strbuf, sizeof(strbuf), "Unexpected symbol '%s' at state '%zu'", symbol_to_str[parseinfo->idx.sym], parseinfo->idx.state);
break;
case LR_ERR_NO_GOTO_ENTRY:
- snprintf(strbuf, sizeof(strbuf), "No GOTO state for symbol '%s' at state '%zu'", symbol_to_str[errinfo->idx.sym], errinfo->idx.state);
+ snprintf(strbuf, sizeof(strbuf), "No GOTO state for symbol '%s' at state '%zu'", symbol_to_str[parseinfo->idx.sym], parseinfo->idx.state);
break;
+ default: break;
}
return strbuf;
@@ -205,7 +214,7 @@ struct token *toklist_peek() { return toklist + tok; }
symbol token_sym(struct token *t) { return t->s; }
intptr_t token_val(struct token *t) { return (intptr_t)&t->v; }
-intmax_t none(intmax_t *stack_head) {(void)stack_head; return 0;}
+void *none(intmax_t *v, intmax_t *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)