From fec8e3a95becfb3dc2a3eb0f512a120a7a4551c5 Mon Sep 17 00:00:00 2001 From: kartofen Date: Wed, 24 Sep 2025 00:06:54 +0300 Subject: debug info through the lr parser --- lr-parser.c | 73 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'lr-parser.c') 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) -- cgit v1.2.3