#include #include // TODO: - check erros and fail safely and // see connection with the lexer // - standardize this // Requirements #include "parts/symbol.h" #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; #define STACK_CAP 128 static stack_item stack_bottom[STACK_CAP]; static stack_item *stack_head = stack_bottom; int lr_parser(int *value) { #define push(item) do { \ if(++stack_head - stack_bottom < STACK_CAP ) *stack_head = item; \ else { fprintf(stderr, "ERROR: STACK_CAP exceeded\n"); return 1; } \ } while(0) #define pop() (--stack_head) #define eat() toklist_eat() #define peek() toklist_peek() while(1) { struct action a = table[(size_t)*stack_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); break; case ACTION_REDUCE: 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]; 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; } push(lhs); push(semantic_value); push(a_goto.arg); break; case ACTION_ACCEPT: *value = *(stack_head-1); return 0; case ACTION_NOT_SET: default: fprintf(stderr, "ERROR: Unexpected symbol '%d' at state %zu\n", token_sym(peek()), (size_t)*stack_head); return 1; } } return 1; } #ifdef _LR_PARSER_STANDALONE // implement symbol.h enum symbol { PLUS = 0, MINUS, LPAREN, RPAREN, N0, N1, END_INPUT, EP, E, T, N, SYMBOLS_END, }; size_t total_symbols = SYMBOLS_END; IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s)) { return s < SYMBOLS_END; } // implement grammar.h #define PROD(LHS, _, ...) {LHS, (symbol[]){__VA_ARGS__}, sizeof((symbol[]){__VA_ARGS__})/sizeof(symbol)} static struct production _grammar[] = { PROD(EP, ->, E, END_INPUT), PROD(E, -->, E, PLUS, T), PROD(E, -->, E, MINUS, T), PROD(E, -->, T), PROD(T, -->, LPAREN, E, RPAREN), PROD(T, -->, N), PROD(N, -->, N0), PROD(N, -->, N1), }; struct production *grammar = _grammar; size_t total_productions = sizeof(_grammar)/sizeof(*_grammar); // implement table.h struct action **table = (struct action *([])){ (struct action[]){{0, 0},{0, 0},{1, 1},{0, 0},{1, 2},{1, 3},{0, 0},{0, 0},{2, 12},{2, 11},{2, 7},}, (struct action[]){{0, 0},{0, 0},{1, 1},{0, 0},{1, 2},{1, 3},{0, 0},{0, 0},{2, 4},{2, 11},{2, 7},}, (struct action[]){{3, 6},{3, 6},{0, 0},{3, 6},{0, 0},{0, 0},{3, 6},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{3, 7},{3, 7},{0, 0},{3, 7},{0, 0},{0, 0},{3, 7},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{1, 5},{1, 8},{0, 0},{1, 10},{0, 0},{0, 0},{0, 0},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{0, 0},{0, 0},{1, 1},{0, 0},{1, 2},{1, 3},{0, 0},{0, 0},{0, 0},{2, 6},{2, 7},}, (struct action[]){{3, 1},{3, 1},{0, 0},{3, 1},{0, 0},{0, 0},{3, 1},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{3, 5},{3, 5},{0, 0},{3, 5},{0, 0},{0, 0},{3, 5},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{0, 0},{0, 0},{1, 1},{0, 0},{1, 2},{1, 3},{0, 0},{0, 0},{0, 0},{2, 9},{2, 7},}, (struct action[]){{3, 2},{3, 2},{0, 0},{3, 2},{0, 0},{0, 0},{3, 2},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{3, 4},{3, 4},{0, 0},{3, 4},{0, 0},{0, 0},{3, 4},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{3, 3},{3, 3},{0, 0},{3, 3},{0, 0},{0, 0},{3, 3},{0, 0},{0, 0},{0, 0},{0, 0},}, (struct action[]){{1, 5},{1, 8},{0, 0},{0, 0},{0, 0},{0, 0},{4, 0},{0, 0},{0, 0},{0, 0},{0, 0},}, }; size_t table_states = 13; // implement toklist.h struct token { symbol s; int v; }; static struct token toklist[] = {{N0}, {PLUS}, {N1}, {END_INPUT}}; static const size_t ntoklist = sizeof(toklist)/sizeof(*toklist); static size_t tok; struct token *toklist_eat() { if(tok == ntoklist) return toklist + ntoklist-1; return toklist + tok++; } 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; } 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) { int value; if(lr_parser(&value)) return 1; printf("%d\n", value); return 0; } #endif