diff options
| author | kartofen <kartofen.mail.0@protonmail.com> | 2025-09-13 15:24:28 +0300 |
|---|---|---|
| committer | kartofen <kartofen.mail.0@protonmail.com> | 2025-09-13 15:24:28 +0300 |
| commit | db1b9c8dcb0d115217a33c2fe8e0760d49143e11 (patch) | |
| tree | c93743adff3d78ea066c14879b7d2bfeb3ce42fb /lr-parser.c | |
| parent | 46e786db9d1b48b8fbc3502e36f093b755f3e09f (diff) | |
ast nearly build and proper errors
Diffstat (limited to 'lr-parser.c')
| -rw-r--r-- | lr-parser.c | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/lr-parser.c b/lr-parser.c index 336c222..a909f7f 100644 --- a/lr-parser.c +++ b/lr-parser.c @@ -12,84 +12,118 @@ #include "parts/table.h" #include "parts/toklist.h" // and -typedef intptr_t (*semantic_action_fn)(intmax_t *stack_head); +typedef stack_item (*semantic_action_fn)(stack_item *item_head); extern semantic_action_fn *semantic_actions; -typedef intmax_t stack_item; - #define STACK_CAP 128 -static stack_item stack_bottom[STACK_CAP]; -static stack_item *stack_head = stack_bottom; +static stack_item item_bottom[STACK_CAP]; +static stack_item *item_head = item_bottom; + +static int state_bottom[STACK_CAP]; +static int *state_head = state_bottom; static void print_stack() { fprintf(stderr, "STACK: { "); - for(stack_item *s = stack_bottom+1; s <= stack_head; s += 3) + for(int *s = state_bottom+1; s <= state_head; s += 2) fprintf(stderr, "%s ", symbol_to_str[*(symbol *)s]); fprintf(stderr, "}\n\n"); } -int lr_parser(intptr_t *value) +struct lr_errinfo { + enum lr_errtype { 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) { -#define push(item) do { \ - if(++stack_head - stack_bottom < STACK_CAP ) *stack_head = item; \ - else { fprintf(stderr, "ERROR: STACK_CAP exceeded\n"); print_stack(); return 1; } \ + static struct lr_errinfo errinfo; + +#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; } \ } while(0) -#define pop() (--stack_head) +#define pop(stack_head) (--stack_head) + +#define spush(item) push(state_head, state_bottom, item) +#define spop() pop(state_head) +#define ipush(item) push(item_head, item_bottom, item) +#define ipop() pop(item_head) + #define eat() toklist_eat() #define peek() toklist_peek() while(1) { - struct action a = table[(size_t)*stack_head][token_sym(peek())]; + struct action a = table[(size_t)*state_head][token_sym(peek())]; switch(a.type) { case ACTION_SHIFT:; struct token *t = eat(); - push(token_sym(t)); - push(token_val(t)); - push(a.arg); + ipush(*(stack_item*)token_val(t)); + spush(token_sym(t)); + spush(a.arg); #ifdef _LR_PARSER_DEBUG fprintf(stderr, "SHIFT %s\n", symbol_to_str[token_sym(t)]); print_stack(); #endif break; case ACTION_REDUCE: - intptr_t semantic_value = semantic_actions[a.arg](stack_head); - for(size_t i = 0; i < 3*grammar[a.arg].nRHS; i++) pop(); + stack_item semantic_value = semantic_actions[a.arg](item_head); + for(size_t i = 0; i < grammar[a.arg].nRHS; i++) { + ipop(); spop(); spop(); + } symbol lhs = grammar[a.arg].LHS; - struct action a_goto = table[(size_t)*stack_head][lhs]; + struct action a_goto = table[(size_t)*state_head][lhs]; if(a_goto.type != ACTION_GOTO) { - fprintf(stderr, - "ERROR: Expected goto action for token '%d' at state %zu\n", - lhs, (size_t)*stack_head); - return 1; + errinfo = (struct lr_errinfo){.type = LR_ERR_NO_GOTO_ENTRY, .idx = {lhs, (size_t)*state_head}}; + return &errinfo; } - push(lhs); - push(semantic_value); - push(a_goto.arg); + ipush(semantic_value); + spush(lhs); + spush(a_goto.arg); #ifdef _LR_PARSER_DEBUG fprintf(stderr, "READUCE %s\n", symbol_to_str[lhs]); + print_stack(); #endif break; case ACTION_ACCEPT: - for(size_t i = 0; i < 3; i++) push(0); // todo: better fix for reducing the final production expecting an END_INPUT on the stack - *value = semantic_actions[0](stack_head); - return 0; + 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; case ACTION_NOT_SET: default: - fprintf(stderr, - "ERROR: Unexpected symbol '%s' at state %zu\n", - symbol_to_str[token_sym(peek())], (size_t)*stack_head); - // Expected ... - print_stack(); - return 1; + errinfo = (struct lr_errinfo){.type = LR_ERR_UNEXPECTED_SYMBOL, .idx = {token_sym(peek()), (size_t)*state_head}}; + return &errinfo; } } +} + +char *lr_err_str(struct lr_errinfo *errinfo) +{ + // TODO: check if strbuf cap is exceeded + static char strbuf[128]; + + switch(errinfo->type) { + case LR_ERR_STACKCAP_EXCEEDED: + snprintf(strbuf, sizeof(strbuf), "LR parser stack capacity of %zu has been exceeded", errinfo->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); + 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); + break; + } - return 1; + return strbuf; } #ifdef _LR_PARSER_STANDALONE @@ -107,6 +141,7 @@ enum symbol { SYMBOLS_END, }; +char **symbol_to_str = (char*[]){"+", "-", "(", ")", "0", "1", "IN_END", "EP", "E", "T", "N", "S_END"}; size_t total_symbols = SYMBOLS_END; IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s)) { return s < SYMBOLS_END; } @@ -152,7 +187,7 @@ size_t table_states = 13; // implement toklist.h struct token { symbol s; - int v; + intmax_t v; }; static struct token toklist[] = {{N0, 0}, {PLUS, 0}, {N1, 0}, {END_INPUT, 0}}; @@ -167,18 +202,18 @@ struct token *toklist_eat() } struct token *toklist_peek() { return toklist + tok; } -symbol token_sym(struct token *t) { return t->s; } -int token_val(struct token *t) { return t->v; } +symbol token_sym(struct token *t) { return t->s; } +intptr_t token_val(struct token *t) { return (intptr_t)&t->v; } -intptr_t none(intmax_t *stack_head) {(void)stack_head; return 0;} +intmax_t none(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) { - intptr_t value; + intmax_t value; if(lr_parser(&value)) return 1; - printf("%jd\n", value); + printf("%ld\n", value); return 0; } |
