diff options
author | JSDurand <mmemmew@gmail.com> | 2022-01-31 09:23:20 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2022-01-31 09:23:20 +0800 |
commit | a8bd5e9d85ac9928bd29add82e887f82642af893 (patch) | |
tree | 74e377f9fccffc2779ff97fa0bd8ad180b9c865c /src/test | |
parent | e555c88b8107caf886da229444c2bed1aaef6c2c (diff) |
test/check_cnp: working algorithm
I now have a working algorithm in test/check_cnp. It can correctly
parse the grammar for an esoteric language called "Brainfuck". This
language does not matter. What matters is that it contains
parentheses. So this shows that at least for grammars as complex as
parentheses, this parser works well. Haha.
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/check_cnp.c | 291 | ||||
-rw-r--r-- | src/test/check_ht.c | 4 | ||||
-rw-r--r-- | src/test/check_reader.c | 2 |
3 files changed, 296 insertions, 1 deletions
diff --git a/src/test/check_cnp.c b/src/test/check_cnp.c new file mode 100644 index 0000000..00c8a64 --- /dev/null +++ b/src/test/check_cnp.c @@ -0,0 +1,291 @@ +#include "../cnp.h" + +#define READ_INTO_CPA(N, U, L, I, VA, VI, CP) do { \ + U = new_utf8(N, L); \ + I = get_info((str *)U, 0); \ + VA = MYALLOC(NUM, 2); \ + VI = 0; \ + for (NUM index = 0; \ + I.value >= 0 && index < str_length((str *) U); \ + index += I.step, VI++) { \ + I = get_info((str *)U, index); \ + *(VA+VI) = I.value; \ + } \ + CP = MYALLOC(cpa, 1); \ + CP->array = VA; \ + CP->size = VI; \ + add_to_list(names, CP); \ + destroy_str((str *)U, 1); \ + } while (0) + +#define READ_TNT_STRING(LEFT, FORMAT, LEN, ...) do { \ + tnt_string = new_tnt_string(FORMAT, LEN, __VA_ARGS__); \ + if (!tnt_string) { \ + fleprintf("left = %d, f = %s, l = %d, " \ + "cannot create tnt string\n", \ + LEFT, FORMAT, LEN); \ + map_list(rules, destroy_rule_and_free_all); \ + destroy_list(rules, 0); \ + map_list(names, destroy_cpa_and_free_all); \ + destroy_list(names, 0); \ + return 1; \ + } \ + rule = new_rule(LEFT, tnt_string); \ + add_to_list(rules, rule); \ + } while (0) + +int +main(int UNUSED argc, char ** UNUSED argv) +{ + /* have a grammar for testing */ + List *tnt_string = NULL; + Rule *rule = NULL; + List *rules = new_list(); + List *names = new_list(); + + char *name = MYALLOC(char, 2); + *(name+1) = 0; + *name = 'B'; + + utf8* uname = NULL; + + str_info info = EMPTY_STR_INFO; + + NUM *varray = NULL; + NUM vindex = 0; + cpa *cpap = NULL; + + READ_INTO_CPA(name, uname, 1, info, varray, vindex, cpap); + + name = MYALLOC(char, 3); + *(name+1) = 0; + *name = 'U'; + + READ_INTO_CPA(name, uname, 1, info, varray, vindex, cpap); + + /* name = MYALLOC(char, 2); + * *(name+1) = 0; + * *name = 'F'; + * + * READ_INTO_CPA(name, uname, 1, info, varray, vindex, cpap); + * + * name = MYALLOC(char, 2); + * *(name+1) = 0; + * *name = 'D'; + * + * READ_INTO_CPA(name, uname, 1, info, varray, vindex, cpap); */ + + READ_TNT_STRING(0, "nn", 2, (NT) 1, (NT) 0); + rule = new_rule(0, new_list()); + add_to_list(rules, rule); + + READ_TNT_STRING(1, "t", 1, (T) '>'); + READ_TNT_STRING(1, "t", 1, (T) '<'); + READ_TNT_STRING(1, "t", 1, (T) '+'); + READ_TNT_STRING(1, "t", 1, (T) '-'); + READ_TNT_STRING(1, "t", 1, (T) ','); + READ_TNT_STRING(1, "t", 1, (T) '.'); + READ_TNT_STRING(1, "tnt", 3, (T) '[', (NT) 0, (T) ']'); + + Grammar *g = new_grammar(); + + build_grammar(g, rules, names); + + print_grammar(g); + + utf8 *string = new_utf8("[,[.[+]]-]", 10); + + printf("\nPrinting the input...\n%s\n", get_data((str *) string)); + + Environment *env = new_env(g, (str *) string); + + if (crf_add_node(env_crfp(env), (pair2) { 0 })) goto cleanup; + + nt_add(env, 0, 0); + + CHECK_ENV_ERROR(env, goto cleanup;); + + NUM current_grade = 0; + + prodecor *current_prodecor = NULL; + + Rule_group *rg = NULL; + List *right = NULL, *tnts = NULL; + + NUM *num_string = NULL, num_string_len = 0; + BOOL errorp = 0; + + env_str(env, &num_string, &num_string_len); + + while ((current_prodecor = + pop_procr(env_r(env), env_u(env), ¤t_grade))) { + /* fleprintf("{ %ld, %ld, %ld, %ld, %ld }\n", + * current_prodecor->x, current_prodecor->y, + * current_prodecor->z, current_prodecor->w, + * current_grade); + * print_procr(env_r(env)); */ + + /* different cases */ + + rg = grammar_rule(env_grammar(env), current_prodecor->x); + right = rg_nth(rg, current_prodecor->y); + + /* separate the empty rules out */ + if (list_length(right) == 0) { + errorp = + bsr_add(env_grammar(env), env_bsrp(env), + current_prodecor->x, current_prodecor->y, 0, + current_grade, current_grade, current_grade); + + if (errorp) goto cleanup; + + if (env_follow_p(env, current_prodecor->x, + *(num_string+current_grade))) { + rtn(env, current_prodecor->x, + current_prodecor->w, current_grade); + } + + goto continue_label; + } + + /* fleprintf0("non empty rule\n"); */ + + /* if at the end of a rule, return if possible */ + if (current_prodecor->z == list_length(right)) { + if (env_follow_p(env, current_prodecor->x, + *(num_string+current_grade))) { + rtn(env, current_prodecor->x, + current_prodecor->w, current_grade); + } + + goto continue_label; + } + + /* fleprintf0("not at the end of the rule\n"); */ + + /* if at the start of a rule, no need for test_select */ + if (current_prodecor->z == 0) { + /* fleprintf0("at the start of the rule\n"); */ + current_prodecor->z = 1; + + /* otherwise test select */ + } else { + /* fleprintf0("start by test select\n"); */ + tnts = + array_to_list(list_array(right)+current_prodecor->z, + list_length(right)-current_prodecor->z); + if (test_select(env, *(num_string+current_grade), + current_prodecor->x, tnts)) { + /* fleprintf0("successful test\n"); */ + free(tnts); + tnts = NULL; + ++(current_prodecor->z); + } else { + /* fleprintf0("failed test\n"); */ + free(tnts); + tnts = NULL; + goto continue_label; + } + } + + CHECK_ENV_ERROR(env, goto cleanup;); + + /* while there are terminals */ + while (((TNT *) list_nth(right, current_prodecor->z-1))->type == + TERMINAL) { + /* fleprintf0("found terminal\n"); */ + /* add to BSR set */ + errorp = + bsr_add(env_grammar(env), env_bsrp(env), + current_prodecor->x, current_prodecor->y, + current_prodecor->z, current_prodecor->w, + current_grade, current_grade+1); + + if (errorp) goto cleanup; + + current_grade++; + + /* if at the end of the rule, return if possible */ + if (current_prodecor->z == list_length(right)) { + if (env_follow_p(env, current_prodecor->x, + *(num_string+current_grade))) { + /* fleprintf0("we choose to return\n"); */ + rtn(env, current_prodecor->x, + current_prodecor->w, current_grade); + /* fleprintf0("hi\n"); */ + } + + goto continue_label; + } + /* fleprintf0("terminal not at the end\n"); */ + /* else test select */ + tnts = + array_to_list(list_array(right)+current_prodecor->z, + list_length(right)-current_prodecor->z); + if (test_select(env, *(num_string+current_grade), + current_prodecor->x, tnts)) { + /* fleprintf0("Successful test\n"); */ + free(tnts); + tnts = NULL; + (current_prodecor->z)++; + } else { + /* fleprintf0("Failed test\n"); */ + /* printf("next thing is "); */ + /* print_tnt(list_nth(right, current_prodecor->z)); */ + /* printf("\n"); */ + free(tnts); + tnts = NULL; + goto continue_label; + } + } + + /* fleprintf0("encountered non-terminal\n"); */ + + /* when a nonterminal is encountered, we call it */ + cnp_call(env, (pair3) { + .x = current_prodecor->x, + .y = current_prodecor->y, + .z = current_prodecor->z + }, current_prodecor->w, current_grade); + + /* fleprintf("after call { %ld, %ld, %ld, %ld, %ld }\n", + * current_prodecor->x, current_prodecor->y, + * current_prodecor->z, current_prodecor->w, + * current_grade); */ + + continue_label: + + CHECK_ENV_ERROR(env, goto cleanup;); + + free(current_prodecor); + } + + cleanup: + bsr_print(env_bsrp(env), env_grammar(env), 1); + + destroy_env(env); + + destroy_grammar(g, 1); + + destroy_list(rules, 1); + + free(string); + + return 0; +} + +/* archives + + printf("\nprint first for 0:\n"); + env_print_first(env, 0); + + printf("\nprint first for 1:\n"); + env_print_first(env, 1); + + printf("\nprint follow for 0:\n"); + env_print_follow(env, 0); + + printf("\nprint follow for 1:\n"); + env_print_follow(env, 1); + + */ diff --git a/src/test/check_ht.c b/src/test/check_ht.c index b572549..62a7bee 100644 --- a/src/test/check_ht.c +++ b/src/test/check_ht.c @@ -231,6 +231,10 @@ int main(int UNUSED argc, char ** UNUSED argv) ht_find(htp, &testk4)); } + ht_reset(htp, DELETE_KEY); + + printf("After reset the size is %ld\n", ht_size(htp)); + destroy_ht(htp, DESTROY_KEY_SELF); return 0; diff --git a/src/test/check_reader.c b/src/test/check_reader.c index 3184e41..a4e184f 100644 --- a/src/test/check_reader.c +++ b/src/test/check_reader.c @@ -11,7 +11,7 @@ main(U_ATTR int argc, U_ATTR char **argv) { /* return 77; */ - char *file_name = "test.txt"; + char *file_name = "brainfuck.bnf"; char *buffer = MYALLOC(char, 512); NUM buffer_size = 0; |