diff options
| author | kartofen <kartofen.mail.0@protonmail.com> | 2025-08-03 23:53:24 +0300 |
|---|---|---|
| committer | kartofen <kartofen.mail.0@protonmail.com> | 2025-08-03 23:53:24 +0300 |
| commit | 1c83c514c8108fccfec9764da5e4563b98eb871b (patch) | |
| tree | ccc6657a0b24900a17cf90cfd0676c8123492566 | |
| parent | 059ee9afcc575572f87f224c93288e2835cd1a52 (diff) | |
calc implemented in my grammar
| -rwxr-xr-x | build.sh | 20 | ||||
| -rw-r--r-- | demos/sample-files/calc.g | 26 | ||||
| -rw-r--r-- | demos/sample-files/gram-defs.c | 71 | ||||
| -rw-r--r-- | demos/sample-files/gram-skeleton.c | 48 | ||||
| -rw-r--r-- | lr-parser.c | 1 |
5 files changed, 103 insertions, 63 deletions
@@ -4,7 +4,7 @@ set -e function log { - echo "-> $@" + >&2 echo "-> $@" "$@" } @@ -70,12 +70,22 @@ shared demos/sample-files/lalr-defs # shared demos/sample-files/calc-defs # leak generate-parser "-o bin/calc -t lalr-table bin/calc-defs.so" # cc demos/sample-files/calc-skeleton "" parser -# leak parser "13*10+9" # wrong answer +# leak parser "13*10+9" # leak parser "-13+20" # leak parser "1>52?2+3:53" +# exit 0 -# --- Grammar Definitino example --- +# --- Grammar Definition example --- shared demos/sample-files/gram-defs leak generate-parser "-o bin/gram -t lalr-table bin/gram-defs.so" -cc demos/sample-files/gram-skeleton "" parser -leak parser +cc demos/sample-files/gram-skeleton "" gram-parser + +leak gram-parser < demos/sample-files/calc.g > bin/calc-gram.c + +shared bin/calc-gram +leak generate-parser "-o bin/calc -t lalr-table bin/calc-gram.so" +cc demos/sample-files/calc-skeleton "" calc-parser + +leak calc-parser "13*10+9" +leak calc-parser "-13+20" +leak calc-parser "1>52?2+3:53" diff --git a/demos/sample-files/calc.g b/demos/sample-files/calc.g new file mode 100644 index 0000000..804e072 --- /dev/null +++ b/demos/sample-files/calc.g @@ -0,0 +1,26 @@ +-terminal PLUS MINUS TIMES MORE LESS EQUA + LPAREN RPAREN QMARK COLON NUM; + +-nonterminal EP E. + +-left LPAREN; +-left 5; +-left TIMES; +-left MINUS PLUS; +-left MORE LESS EQUA; +-left COLON 7; +-left QMARK. + +EP: E { v = A(0); }; + +E: E PLUS E { v = A(0) + A(2); } + | E MINUS E { v = A(0) - A(2); } + | E TIMES E { v = A(0) * A(2); } + | LPAREN E RPAREN { v = A(1); } + | MINUS E { v = - A(1); } + | E QMARK E COLON E { v = A(0) ? A(2) : A(4); } + | E QMARK E { v = A(0) ? A(2) : 0; } + | E MORE E { v = A(0) > A(2); } + | E LESS E { v = A(0) < A(2); } + | E EQUA E { v = A(0) == A(2); } + | NUM { v = A(0); }. diff --git a/demos/sample-files/gram-defs.c b/demos/sample-files/gram-defs.c index b93a950..49329bd 100644 --- a/demos/sample-files/gram-defs.c +++ b/demos/sample-files/gram-defs.c @@ -21,41 +21,42 @@ IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s)) { return s < SYMBOLS_END; } #include "parts/grammar.h" #define PROD(LHS, _, ...) {LHS, (symbol[]){__VA_ARGS__}, sizeof((symbol[]){__VA_ARGS__})/sizeof(symbol)} -#define GRAMMAR_ACTION_DEF(X) \ - X(PROD(Sp, -->, A, B, C, END_INPUT), "") \ - \ - X(PROD(A, -->, TERMINAL, Idenlist, \ - SEMICOL, NONTERM, Idenlist, DOT), "handle_type(A(1), A(4))") \ - \ - X(PROD(B, -->, Preclist), "handle_prec(A(0));") \ - X(PROD(Preclist, -->, Prec, SEMICOL, Preclist), \ - "v = list_new_head(A(2), A(0));") \ - X(PROD(Preclist, -->, Prec, DOT), "v = A(0);") \ - X(PROD(Prec, -->, LEFT, IorNlist), \ - "v = prec_new(A(1), PRECEDENCE_LEFT_ASSOC);") \ - X(PROD(Prec, -->, RIGHT, IorNlist), \ - "v = prec_new(A(1), PRECEDENCE_RIGHT_ASSOC);") \ - \ - X(PROD(C, -->, Prodlist), "handle_prod(A(0));") \ - X(PROD(Prodlist, -->, Prod, SEMICOL, Prodlist), \ - "v = list_new_head(A(2), A(0));") \ - X(PROD(Prodlist, -->, Prod, DOT), "v = A(0);") \ - X(PROD(Prod, -->, IDEN, COLON, Actionlist), \ - "v = prod_new(A(0), A(2));") \ - X(PROD(Actionlist, -->, Idenlist, ACTION, PIPE, Actionlist), \ - "v = list_new_head(A(3), action_new(A(0), A(1)));") \ - X(PROD(Actionlist, -->, Idenlist, ACTION), \ - "v = action_new(A(0), A(1));") \ - \ - X(PROD(Idenlist, -->, IDEN, Idenlist), \ - "v = list_new_head(A(1), ptr_new(A(0)));") \ - X(PROD(Idenlist, -->, IDEN), "v = ptr_new(A(0));") \ - X(PROD(IorNlist, -->, IDEN, IorNlist), \ - "v = list_new_head(A(1), ptr_new(A(0)));") \ - X(PROD(IorNlist, -->, IDEN), "v = ptr_new(A(0));") \ - X(PROD(IorNlist, -->, NUM, IorNlist), \ - "v = list_new_head(A(1), num_new(A(0)));") \ - X(PROD(IorNlist, -->, NUM), "v = num_new(A(0));") \ +#define GRAMMAR_ACTION_DEF(X) \ + X(PROD(Sp, -->, A, B, C, END_INPUT), "") \ + \ + X(PROD(A, -->, TERMINAL, Idenlist, \ + SEMICOL, NONTERM, Idenlist, DOT), \ + "handle_type(A(1), A(4))") \ + \ + X(PROD(B, -->, Preclist), "handle_prec(A(0));") \ + X(PROD(Preclist, -->, Prec, SEMICOL, Preclist), \ + "v = list_new_head(A(2), A(0));") \ + X(PROD(Preclist, -->, Prec, DOT), "v = A(0);") \ + X(PROD(Prec, -->, LEFT, IorNlist), \ + "v = prec_new(A(1), PRECEDENCE_LEFT_ASSOC);") \ + X(PROD(Prec, -->, RIGHT, IorNlist), \ + "v = prec_new(A(1), PRECEDENCE_RIGHT_ASSOC);") \ + \ + X(PROD(C, -->, Prodlist), "handle_prod(A(0));") \ + X(PROD(Prodlist, -->, Prod, SEMICOL, Prodlist), \ + "v = list_new_head(A(2), A(0));") \ + X(PROD(Prodlist, -->, Prod, DOT), "v = A(0);") \ + X(PROD(Prod, -->, IDEN, COLON, Actionlist), \ + "v = prod_new(A(0), A(2));") \ + X(PROD(Actionlist, -->, Idenlist, ACTION, PIPE, Actionlist), \ + "v = list_new_head(A(3), action_new(A(0), A(1)));") \ + X(PROD(Actionlist, -->, Idenlist, ACTION), \ + "v = action_new(A(0), A(1));") \ + \ + X(PROD(Idenlist, -->, IDEN, Idenlist), \ + "v = list_new_head(A(1), ptr_new(A(0)));") \ + X(PROD(Idenlist, -->, IDEN), "v = ptr_new(A(0));") \ + X(PROD(IorNlist, -->, IDEN, IorNlist), \ + "v = list_new_head(A(1), ptr_new(A(0)));") \ + X(PROD(IorNlist, -->, IDEN), "v = ptr_new(A(0));") \ + X(PROD(IorNlist, -->, NUM, IorNlist), \ + "v = list_new_head(A(1), num_new(A(0)));") \ + X(PROD(IorNlist, -->, NUM), "v = num_new(A(0));") \ #define X_GRAMMAR(G, A) G, #define X_ACTION(G, A) A, diff --git a/demos/sample-files/gram-skeleton.c b/demos/sample-files/gram-skeleton.c index a5899ac..7a54548 100644 --- a/demos/sample-files/gram-skeleton.c +++ b/demos/sample-files/gram-skeleton.c @@ -4,10 +4,13 @@ #include <stdint.h> #include <ctype.h> +#define INPUT_CAP 4096 +#define ARENA_CAP 4096 + #define ARENA_IMPLEMENTATION #include "util/arena.h" -static char buf[2048]; +static char buf[ARENA_CAP]; static struct arena_ctx global_arena; static void *xalloc(size_t sz) { void *addr = arena_allocate(&global_arena, sz); @@ -55,26 +58,26 @@ struct strnptr_entry { struct list_head *ptr_new(void *ptr) new_entry(struct ptr_entry, entry, { entry->data = (intptr_t)ptr; - }); + }) struct list_head *num_new(intmax_t num) new_entry(struct ptr_entry, entry, { entry->data = (num << 1) | 0x1; - }); + }) struct list_head *prec_new(struct list_head *idenlist, enum precedence_flag flag) new_entry(struct prec_entry, entry, { entry->ptrlist = idenlist; entry->flag = flag; - }); + }) struct list_head *action_new(struct list_head *idenlist, char *action) new_entry(struct strnptr_entry, entry, { entry->str = action; entry->ptrlist = idenlist; - }); + }) struct list_head *prod_new(char *iden, struct list_head *actionlist) new_entry(struct strnptr_entry, entry, { entry->str = iden; entry->ptrlist = actionlist; - }); + }) void handle_type(struct list_head *terminals, struct list_head *nonterminals) { @@ -87,6 +90,8 @@ void handle_type(struct list_head *terminals, struct list_head *nonterminals) printf("%s, ", (char *)entry->data); printf("SYMBOLS_END };\n"); + printf("size_t total_symbols = %zu;\n", list_len(terminals) + list_len(nonterminals) + 2); + printf("char **symbol_to_str = (char *([])){ "); list_for_each_entry(struct ptr_entry, entry, list, terminals) printf("\"%s\", ", (char *)entry->data); @@ -99,6 +104,7 @@ void handle_type(struct list_head *terminals, struct list_head *nonterminals) (char *)container_of(nonterminals, struct ptr_entry, list)->data); printf("IMPLEMENT_FUNCPTR(int, symbol_is_input_end, (symbol s)) { return s == END_INPUT; }\n"); printf("IMPLEMENT_FUNCPTR(int, symbol_is_valid, (symbol s)) { return s < SYMBOLS_END; }\n"); + } void handle_prec(struct list_head *preclist) @@ -128,7 +134,11 @@ void handle_prod(struct list_head *prodlist) printf("#include \"parts/grammar.h\"\n"); printf("struct production *grammar = (struct production[]){\n"); list_for_each_entry(struct strnptr_entry, e1, list, prodlist) { + if(productions == 0) + list_add(list_get_tail(list_entry(e1->ptrlist, struct strnptr_entry, list)->ptrlist), + ptr_new("END_INPUT")); productions += list_len(e1->ptrlist); + list_for_each_entry(struct strnptr_entry, e2, list, e1->ptrlist) { printf("{%s, (symbol[]){ ", e1->str); list_for_each_entry(struct ptr_entry, e3, list, e2->ptrlist) @@ -173,21 +183,7 @@ static char *next_token(char *str); symbol token_sym(struct token *t) { return t->s; } intptr_t token_val(struct token *t) { return t->v; } -static char *input = (char []){ - "-terminal ID EQUAL STAR;" - "-nonterminal EP E L R." - "" - "-left ID;" - "-right STAR;" - "-left EQUAL." - "" - "EP: E END_INPUT {1};" - "E : L EQUAL R {2}" - " | R {3};" - "L : STAR R {4}" - " | ID {5};" - "R : L {6}." -}; +static char *input; struct token *toklist_eat() { @@ -203,9 +199,15 @@ struct token *toklist_peek() { return &tok; } int main(void) { - global_arena = ARENA_CTX_INIT(buf, sizeof(buf)); + static char input_buf[INPUT_CAP]; + if(fread(input_buf, INPUT_CAP, 1, stdin) == INPUT_CAP) { + fprintf(stderr, "INPUT_CAP reached\n"); + return 1; + } - input = next_token(input); + global_arena = ARENA_CTX_INIT(buf, ARENA_CAP); + + input = next_token(input_buf); intptr_t value; if(lr_parser(&value)) { diff --git a/lr-parser.c b/lr-parser.c index 621a9e7..bca8a52 100644 --- a/lr-parser.c +++ b/lr-parser.c @@ -60,6 +60,7 @@ int lr_parser(intptr_t *value) push(a_goto.arg); 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; case ACTION_NOT_SET: |
