From d3ed2864afd3d470a39c7ef2ec1a53deaae18d14 Mon Sep 17 00:00:00 2001 From: c Date: Sat, 6 Jan 2024 22:16:06 -0500 Subject: Tests worked out. --- Makefile | 3 +- examples/hello.halk | 2 +- src/include/syntax.h | 2 +- src/lexer.c | 4 +- src/tree.c | 2 +- test/include/test.h | 4 +- test/parser.c | 187 ++++++++++++++++++++++++++++++----------- test/tree.c | 230 ++++++++++++++++++++++++++++++++++++++++++++------- 8 files changed, 345 insertions(+), 89 deletions(-) diff --git a/Makefile b/Makefile index e4a0a22..03203b4 100644 --- a/Makefile +++ b/Makefile @@ -58,5 +58,6 @@ clean: me a: @exit + sandwich: - @[ "$(USER)" = "root" ] && echo "Okay." || echo "What? Make it yourself." + @[ "$(shell id -u)" = 0 ] && echo "Okay." || echo "What? Make it yourself." diff --git a/examples/hello.halk b/examples/hello.halk index 0fb2fd6..4eeeeb7 100644 --- a/examples/hello.halk +++ b/examples/hello.halk @@ -2,7 +2,7 @@ :str:hello = "Hello"; ` Define a variable "hello" with the type "str". ` -:str:greet.:str:target = strcat.hello, ", ", target; ` Define a function "greet" that returns a "str" and accepts an +:str:greet.:str:target = strcat.hello, " ", target, "."; ` Define a function "greet" that returns a "str" and accepts an argument "target", also of type "str". ` ` some more functions ` diff --git a/src/include/syntax.h b/src/include/syntax.h index ab92845..2938178 100644 --- a/src/include/syntax.h +++ b/src/include/syntax.h @@ -14,7 +14,7 @@ #define SYNTAX_APPLY '.' #define SYNTAX_LIST_DELIM ',' #define SYNTAX_TAG_DELIM ':' -#define SYNTAX_NAMESPACE_DELIM '!' +#define SYNTAX_NAMESPACE_DELIM ':' #define SYNTAX_LBLOCK '{' #define SYNTAX_RBLOCK '}' #define SYNTAX_RLIST '[' diff --git a/src/lexer.c b/src/lexer.c index 74bea85..ce7dcc0 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -63,9 +63,9 @@ void lexer_do_reg(lexer_t* lexer) { case SYNTAX_TAG_DELIM: lexer->state = LEXER_STATE_TAG; break; - case SYNTAX_NAMESPACE_DELIM: +/* case SYNTAX_NAMESPACE_DELIM: lexer_add_current_char(lexer, TOKEN_NAMESPACE_DELIM); - break; + break; */ case SYNTAX_SET: lexer_add_current_char(lexer, TOKEN_SET); break; diff --git a/src/tree.c b/src/tree.c index 4729200..a024371 100644 --- a/src/tree.c +++ b/src/tree.c @@ -98,7 +98,7 @@ int tree_cmp(tree_t* tree_0, tree_t* tree_1) { switch (tree_0->type) { case TREE_TYPE_BLOCK: return tree_cmp(tree_0->data.block.val, tree_1->data.block.val) && - tree_cmp(tree_0->data.block.val, tree_1->data.block.val); + tree_cmp(tree_0->data.block.nxt, tree_1->data.block.nxt); break; case TREE_TYPE_EXPR: return tree_cmp(tree_0->data.expr.val, tree_1->data.expr.val); diff --git a/test/include/test.h b/test/include/test.h index 4638a1e..9a2aa5a 100644 --- a/test/include/test.h +++ b/test/include/test.h @@ -6,8 +6,6 @@ extern unsigned int TESTS_RUN; extern unsigned int TESTS_PASSED; -#define HIDE(THE) do { THE } while ( 0 ); - #define ASSERT(EXPR) \ TESTS_RUN++; \ (EXPR && ++TESTS_PASSED) ? \ @@ -19,4 +17,4 @@ extern unsigned int TESTS_PASSED; log_yay("%s: All %d tests passed!", __FILE__, TESTS_RUN) : \ log_err("%d/%d tests failed.", TESTS_RUN - TESTS_PASSED, TESTS_RUN); -#endif /* ifndef TEST_H */ +#endif diff --git a/test/parser.c b/test/parser.c index 06a305e..78e4066 100644 --- a/test/parser.c +++ b/test/parser.c @@ -6,68 +6,157 @@ unsigned int TESTS_RUN = 0, TESTS_PASSED = 0; +#define PARSER_SETUP(SRC) \ + pp = pp_init(SRC); \ + pp_run(pp); \ + lexer = lexer_init(pp->psrc); \ + lexer_run(lexer); \ + parser = parser_init(lexer->tokenl); \ + parser_run(parser); + int main(int argc, char** argv) { tree_t* tree_0; pp_t* pp; lexer_t* lexer; parser_t* parser; - tree_0 = tree_init(TREE_TYPE_BLOCK); - tree_t* treep_00 = tree_0->data.block.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_01 = treep_00->data.expr.val = tree_init(TREE_TYPE_DEF); - tree_t* treep_02 = treep_01->data.def.tag = tree_init(TREE_TYPE_TAG); - treep_02->data.tag.val = "int"; - tree_t* treep_03 = treep_02->data.tag.nxt = tree_init(TREE_TYPE_TAG); - treep_03->data.tag.val = "f"; - treep_03->data.tag.nxt = NULL; - treep_01->data.def.arg = NULL; - tree_t* treep_04 = treep_01->data.def.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_05 = treep_04->data.expr.val = tree_init(TREE_TYPE_BLOCK); - tree_t* treep_06 = treep_05->data.block.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_07 = treep_06->data.expr.val = tree_init(TREE_TYPE_CALL); - treep_07->data.call.target = "a"; - tree_t* treep_08 = treep_07->data.call.arg = tree_init(TREE_TYPE_CARG); - tree_t* treep_09 = treep_08->data.carg.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_10 = treep_09->data.expr.val = tree_init(TREE_TYPE_CALL); - treep_10->data.call.target = "b"; - treep_10->data.call.arg = NULL; - treep_08->data.carg.nxt = NULL; - tree_t* treep_11 = treep_05->data.block.nxt = tree_init(TREE_TYPE_BLOCK); - tree_t* treep_12 = treep_11->data.block.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_13 = treep_12->data.expr.val = tree_init(TREE_TYPE_CALL); - treep_13->data.call.target = "c"; - tree_t* treep_14 = treep_13->data.call.arg = tree_init(TREE_TYPE_CARG); - tree_t* treep_15 = treep_14->data.carg.val = tree_init(TREE_TYPE_EXPR); - tree_t* treep_16 = treep_15->data.expr.val = tree_init(TREE_TYPE_CALL); - treep_16->data.call.target = "d"; - treep_16->data.call.arg = NULL; - treep_14->data.carg.nxt = NULL; - treep_11->data.block.nxt = NULL; - tree_0->data.block.nxt = NULL; - - /* - - [block] + /* Simple empty block. */ + char src_0[] = ""; + + /* + + [block] + val: + NULL + nxt: + NULL + + */ + + tree_0 = tree_init(TREE_TYPE_BLOCK); + tree_0->data.block.val = NULL; + tree_0->data.block.nxt = NULL; + + PARSER_SETUP(src_0); + + tree_print(tree_0, 0); + tree_print(parser->tree, 0); + + ASSERT(tree_cmp(parser->tree, tree_0) == 1); + + /* More complicated tree. */ + char src_1[] = "" \ + ":int:f = {" \ + "a.b;" \ + "c.d" + "}"; + /* + [block] + val: + [expression] + val: + [def] + tag: + [tag] + val: + "int" + nxt: + [tag] + val: + "f" + nxt: + NULL + arg: + NULL + val: + [expression] + val: + [block] + val: + [expression] + val: + [call] + target: + "a" + arg: + [carg] + val: + [call] + target: + "b" + arg: + NULL + nxt: + NULL + nxt: + [block] + val: + [expression] + val: + [call] + target: + "c" + arg: + [carg] + val: + [call] + target: + "d" + nxt: + NULL + nxt: + NULL + nxt: + NULL + nxt: + NULL - */ + */ - char src_0[] = "" \ - ":int:f = {" \ - "a.b;" \ - "c.d" - "}"; + tree_0 = tree_init(TREE_TYPE_BLOCK); + tree_t* treep_00 = tree_0->data.block.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_01 = treep_00->data.expr.val = tree_init(TREE_TYPE_DEF); + tree_t* treep_02 = treep_01->data.def.tag = tree_init(TREE_TYPE_TAG); + treep_02->data.tag.val = "int"; + tree_t* treep_03 = treep_02->data.tag.nxt = tree_init(TREE_TYPE_TAG); + treep_03->data.tag.val = "f"; + treep_03->data.tag.nxt = NULL; + treep_01->data.def.arg = NULL; + tree_t* treep_04 = treep_01->data.def.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_05 = treep_04->data.expr.val = tree_init(TREE_TYPE_BLOCK); + tree_t* treep_06 = treep_05->data.block.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_07 = treep_06->data.expr.val = tree_init(TREE_TYPE_CALL); + treep_07->data.call.target = "a"; + tree_t* treep_08 = treep_07->data.call.arg = tree_init(TREE_TYPE_CARG); + tree_t* treep_09 = treep_08->data.carg.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_10 = treep_09->data.expr.val = tree_init(TREE_TYPE_CALL); + treep_10->data.call.target = "b"; + treep_10->data.call.arg = NULL; + treep_08->data.carg.nxt = NULL; + tree_t* treep_11 = treep_05->data.block.nxt = tree_init(TREE_TYPE_BLOCK); + tree_t* treep_12 = treep_11->data.block.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_13 = treep_12->data.expr.val = tree_init(TREE_TYPE_CALL); + treep_13->data.call.target = "c"; + tree_t* treep_14 = treep_13->data.call.arg = tree_init(TREE_TYPE_CARG); + tree_t* treep_15 = treep_14->data.carg.val = tree_init(TREE_TYPE_EXPR); + tree_t* treep_16 = treep_15->data.expr.val = tree_init(TREE_TYPE_CALL); + treep_16->data.call.target = "d"; + treep_16->data.call.arg = NULL; + treep_14->data.carg.nxt = NULL; + treep_11->data.block.nxt = NULL; + tree_0->data.block.nxt = NULL; - pp = pp_init(src_0); - pp_run(pp); + pp = pp_init(src_0); + pp_run(pp); - lexer = lexer_init(pp->psrc); - lexer_run(lexer); + lexer = lexer_init(pp->psrc); + lexer_run(lexer); - parser = parser_init(lexer->tokenl); - parser_run(parser); + parser = parser_init(lexer->tokenl); + parser_run(parser); - ASSERT(tree_cmp(tree_0, parser->tree)); + ASSERT(tree_cmp(tree_0, parser->tree)); pp_destroy(pp); parser_destroy(parser); diff --git a/test/tree.c b/test/tree.c index b4c6ed8..1b2742c 100644 --- a/test/tree.c +++ b/test/tree.c @@ -17,8 +17,18 @@ int main(int argc, char** argv) { tree_t* tree_tag_1; tree_t* tree_def_0; tree_t* tree_def_1; + tree_t* tree_carg_0; + tree_t* tree_carg_1; tree_t* tree_call_0; tree_t* tree_call_1; + tree_t* tree_call_2; + tree_t* tree_block_0; + tree_t* tree_block_1; + tree_t* tree_block_2; + tree_t* tree_block_3; + tree_t* tree_expr_0; + tree_t* tree_expr_1; + tree_t* tree_expr_2; tree_0 = tree_init(TREE_TYPE_EXPR); tree_1 = tree_init(TREE_TYPE_BLOCK); @@ -29,49 +39,207 @@ int main(int argc, char** argv) { tree_lstr_1 = tree_init(TREE_TYPE_LSTR); tree_tag_0 = tree_init(TREE_TYPE_TAG); tree_tag_1 = tree_init(TREE_TYPE_TAG); + tree_carg_0 = tree_init(TREE_TYPE_CARG); + tree_carg_1 = tree_init(TREE_TYPE_CARG); tree_call_0 = tree_init(TREE_TYPE_CALL); tree_call_1 = tree_init(TREE_TYPE_CALL); + tree_call_2 = tree_init(TREE_TYPE_CALL); + tree_block_0 = tree_init(TREE_TYPE_BLOCK); + tree_block_1 = tree_init(TREE_TYPE_BLOCK); + tree_block_2 = tree_init(TREE_TYPE_BLOCK); + tree_block_3 = tree_init(TREE_TYPE_BLOCK); + tree_expr_0 = tree_init(TREE_TYPE_EXPR); + tree_expr_1 = tree_init(TREE_TYPE_EXPR); + tree_expr_2 = tree_init(TREE_TYPE_EXPR); /* Simple cases with nonexistent trees. */ - ASSERT(tree_cmp(NULL, tree_0) == 0); - ASSERT(tree_cmp(tree_0, NULL) == 0); - ASSERT(tree_cmp(NULL, NULL) == 1); + ASSERT(tree_cmp(NULL, tree_0) == 0); + ASSERT(tree_cmp(tree_0, NULL) == 0); + ASSERT(tree_cmp(NULL, NULL) == 1); /* Test tree types. */ - ASSERT(tree_cmp(tree_0, tree_0) == 1); - ASSERT(tree_cmp(tree_0, tree_1) == 0); + ASSERT(tree_cmp(tree_0, tree_0) == 1); + ASSERT(tree_cmp(tree_0, tree_1) == 0); /* Test lints. */ - tree_lint_0->data.lint.val = 0; - tree_lint_1->data.lint.val = 1; - ASSERT(tree_cmp(tree_lint_0, tree_lint_0) == 1); - ASSERT(tree_cmp(tree_lint_0, tree_lint_1) == 0); + tree_lint_0->data.lint.val = 0; + tree_lint_1->data.lint.val = 1; + ASSERT(tree_cmp(tree_lint_0, tree_lint_0) == 1); + ASSERT(tree_cmp(tree_lint_0, tree_lint_1) == 0); /* Test lstrs. */ - tree_lstr_0->data.lstr.val = "foo"; - tree_lstr_0->data.lstr.len = 3; - tree_lstr_1->data.lstr.val = "bar"; - tree_lstr_1->data.lstr.len = 3; - ASSERT(tree_cmp(tree_lstr_0, tree_lstr_0) == 1); - ASSERT(tree_cmp(tree_lstr_0, tree_lstr_1) == 0); + tree_lstr_0->data.lstr.val = "foo"; + tree_lstr_0->data.lstr.len = 3; + tree_lstr_1->data.lstr.val = "bar"; + tree_lstr_1->data.lstr.len = 3; + ASSERT(tree_cmp(tree_lstr_0, tree_lstr_0) == 1); + ASSERT(tree_cmp(tree_lstr_0, tree_lstr_1) == 0); + tree_lstr_1->data.lstr.val = "barr"; + tree_lstr_1->data.lstr.len = 4; + ASSERT(tree_cmp(tree_lstr_0, tree_lstr_1) == 0); /* Test tags. */ - tree_tag_0->data.tag.val = "int"; - tree_tag_0->data.tag.nxt = NULL; - tree_tag_1->data.tag.val = "str"; - tree_tag_1->data.tag.nxt = NULL; - ASSERT(tree_cmp(tree_tag_0, tree_tag_0) == 1); - ASSERT(tree_cmp(tree_tag_0, tree_tag_1) == 0); - tree_tag_1->data.tag.nxt = tree_tag_0; - ASSERT(tree_cmp(tree_tag_0, tree_tag_1) == 0); - - /* Test calls. */ - tree_call_0->data.call.arg = NULL; - tree_call_0->data.call.target = "foo"; - tree_call_1->data.call.arg = NULL; - tree_call_1->data.call.target = "bar"; - ASSERT(tree_cmp(tree_call_0, tree_call_0) == 1); - ASSERT(tree_cmp(tree_call_0, tree_call_1) == 0); + tree_tag_0->data.tag.val = "int"; + tree_tag_0->data.tag.nxt = NULL; + tree_tag_1->data.tag.val = "str"; + tree_tag_1->data.tag.nxt = NULL; + ASSERT(tree_cmp(tree_tag_0, tree_tag_0) == 1); + ASSERT(tree_cmp(tree_tag_0, tree_tag_1) == 0); + tree_tag_1->data.tag.nxt = tree_tag_0; + ASSERT(tree_cmp(tree_tag_0, tree_tag_1) == 0); + ASSERT(tree_cmp(tree_tag_0, tree_tag_1->data.tag.nxt) == 1); + + /* Test calls without arguments. */ + tree_call_0->data.call.arg = NULL; + tree_call_0->data.call.target = "foo"; + tree_call_1->data.call.arg = NULL; + tree_call_1->data.call.target = "bar"; + ASSERT(tree_cmp(tree_call_0, tree_call_0) == 1); + ASSERT(tree_cmp(tree_call_0, tree_call_1) == 0); + + /* Test calls with one argument. */ + tree_lint_0->data.lint.val = 42; + tree_expr_0->data.expr.val = tree_lint_0; + tree_carg_0->data.carg.val = tree_expr_0; + tree_carg_0->data.carg.nxt = NULL; + + tree_call_0->data.call.arg = tree_carg_0; + tree_call_0->data.call.target = "foo"; + + tree_call_1->data.call.arg = NULL; + tree_call_1->data.call.target = "foo"; + + /* Call with 1 arguments vs call without arguments. */ + ASSERT(tree_cmp(tree_call_0, tree_call_0) == 1); + ASSERT(tree_cmp(tree_call_0, tree_call_1) == 0); + + tree_lint_1->data.lint.val = 43; + tree_expr_1->data.expr.val = tree_lint_1; + tree_carg_1->data.carg.val = tree_expr_1; + tree_carg_1->data.carg.nxt = NULL; + + tree_call_1->data.call.arg = tree_carg_1; + tree_call_1->data.call.target = "foo"; + + /* Calls each with a different single argument of the same type. */ + ASSERT(tree_cmp(tree_call_1, tree_call_1) == 1); + ASSERT(tree_cmp(tree_call_0, tree_call_1) == 0); + + /* Test simple blocks with 1 expression. */ + /* Equivalent halk code: + { + foo; + } + */ + tree_call_0->data.call.arg = NULL; + tree_call_0->data.call.target = "foo"; + tree_expr_0->data.expr.val = tree_call_0; + tree_block_0->data.block.val = tree_expr_0; + tree_block_0->data.block.nxt = NULL; + + /* + Equivalent halk code: + {} + */ + tree_block_1->data.block.val = NULL; + tree_block_1->data.block.nxt = NULL; + + ASSERT(tree_cmp(tree_block_0, tree_block_0) == 1); + ASSERT(tree_cmp(tree_block_0, tree_block_1) == 0); + + /* + Equivalent halk code: + { + bar; + } + */ + tree_call_1->data.call.arg = NULL; + tree_call_1->data.call.target = "bar"; + tree_expr_1->data.expr.val = tree_call_1; + tree_block_1->data.block.val = tree_expr_1; + tree_block_1->data.block.nxt = NULL; + + ASSERT(tree_cmp(tree_block_1, tree_block_1) == 1); + ASSERT(tree_cmp(tree_block_0, tree_block_1) == 0); + + /* Blocks with multiple expressions. */ + /* + Equivalent halk code: + { + foo; + foo; + } + */ + + tree_call_0->data.call.arg = NULL; + tree_call_0->data.call.target = "foo"; + tree_expr_0->data.expr.val = tree_call_0; + + tree_block_0->data.block.val = tree_expr_0; + tree_block_1->data.block.val = tree_expr_0; + tree_block_1->data.block.nxt = NULL; + tree_block_0->data.block.nxt = tree_block_1; + + ASSERT(tree_cmp(tree_block_0, tree_block_0) == 1); + /* {foo;} vs {foo; foo;} */ + ASSERT(tree_cmp(tree_block_1, tree_block_0) == 0); + + /* + Equivalent halk code: + { + bar; + foo; + } + */ + tree_block_2->data.block.val = tree_expr_1; + tree_block_2->data.block.nxt = tree_block_1; + + ASSERT(tree_cmp(tree_block_2, tree_block_2) == 1); + /* {bar; foo;} vs {foo; foo;} */ + ASSERT(tree_cmp(tree_block_2, tree_block_0) == 0); + + /* + Equivalent halk code: + { + foo; + bar; + } + */ + + tree_call_1->data.call.arg = NULL; + tree_call_1->data.call.target = "bar"; + tree_expr_1->data.expr.val = tree_call_1; + + tree_block_2->data.block.val = tree_expr_1; + tree_block_3->data.block.val = tree_expr_0; + tree_block_3->data.block.nxt = tree_block_2; + tree_block_2->data.block.nxt = NULL; + + ASSERT(tree_cmp(tree_block_2, tree_block_2) == 1); + /* {bar;} vs {foo; bar;} */ + ASSERT(tree_cmp(tree_block_2, tree_block_3) == 0); + /* {foo; foo;} vs {foo; bar;} */ + ASSERT(tree_cmp(tree_block_0, tree_block_3) == 0); + + /* Test some more complicated trees. */ + tree_call_2->data.call.arg = NULL; + tree_call_2->data.call.target = "x"; + tree_expr_2->data.expr.val = tree_call_2; + tree_carg_0->data.carg.val = tree_expr_2; + tree_call_0->data.call.arg = tree_carg_0; + tree_call_0->data.call.target = "foo"; + tree_expr_0->data.expr.val = tree_call_0; + tree_block_0->data.block.val = tree_expr_0; + tree_block_0->data.block.nxt = NULL; + + tree_call_1->data.call.arg = NULL; + tree_call_1->data.call.target = "bart"; + tree_expr_1->data.expr.val = tree_call_1; + tree_block_1->data.block.val = tree_expr_1; + tree_block_1->data.block.nxt = tree_block_0; + + ASSERT(tree_cmp(tree_block_0, tree_block_0) == 1); + ASSERT(tree_cmp(tree_block_0, tree_block_1) == 0); TEST_REPORT; return 0; -- cgit v1.2.3