From 87e0d4b3d23a7eb38f0e196eac333c318fef27ea Mon Sep 17 00:00:00 2001 From: c Date: Sat, 27 Jan 2024 22:58:23 -0500 Subject: Added string parsing, and tests for more blocks. cool bug on window rn --- src/include/util.h | 2 +- src/main.c | 21 +++---- src/parser.c | 9 ++- test/include/test.h | 8 ++- test/parser.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++--- test/tree.c | 16 +++-- 6 files changed, 199 insertions(+), 30 deletions(-) diff --git a/src/include/util.h b/src/include/util.h index 15f862e..839d3e4 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -8,7 +8,7 @@ /* Log some debug information. */ void log_dbg(const char*, ...); -/* Log some congratulatory information. */ +/* c: */ void log_yay(const char*, ...); /* Log some information. */ void log_inf(const char*, ...); diff --git a/src/main.c b/src/main.c index d8905b5..55053cd 100644 --- a/src/main.c +++ b/src/main.c @@ -1,26 +1,21 @@ #include "include/main.h" -#ifdef TEST -unsigned int TESTS_RUN; -unsigned int TESTS_PASSED; -#endif - +/* FIXME: Segfaults ~30% of the time. No idea why. Thx future self <3. */ int main(int argc, char* argv[]) { - char* src; - pp_t* pp; + char* src; + pp_t* pp; lexer_t* lexer; parser_t* parser; - /* get source */ + /* Get source. */ src = source_get(argv[1]); - log_dbg("source gotten"); - log_inf("source: %s", src); + log_inf("Source: %s", src); - /* create pre-processor */ + /* Create pre-processor. */ pp = pp_init(src); - log_dbg("preprocessor created"); + log_dbg("Preprocessor created."); - /* pre-process source */ + /* Pre-process source. */ pp_run(pp); free(src); src = pp->psrc; diff --git a/src/parser.c b/src/parser.c index 344ca89..2cf9b2c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -15,6 +15,7 @@ void parser_destroy(parser_t* parser) { if (parser) { free(parser); } } +/* TODO: What if the program begins with a ";"? */ int parser_nxt_token(parser_t* parser) { /* Preserve original token list, to be cleaned up by lexer. */ parser->token = parser->token->nxt; @@ -24,6 +25,7 @@ int parser_nxt_token(parser_t* parser) { return parser->token ? 1 : 0; } +/* I don't know if these need to exist. Guess I'll wait and see… */ int parser_match(parser_t* parser, token_type_t type) { return parser->token->type == type; } @@ -49,9 +51,10 @@ tree_t* parser_parse_lstr(parser_t* parser) { lstr = tree_init(TREE_TYPE_LSTR); lstr->data.lstr.len = strlen(parser->token->val); - /* Swap pointers to allow for future token destruction. */ + /* Move token value to tree, to allow for future token destruction. */ lstr->data.lstr.val = parser->token->val; parser->token->val = NULL; + parser_nxt_token(parser); return lstr; } @@ -63,8 +66,8 @@ tree_t* parser_parse_expr(parser_t* parser) { case TOKEN_TYPE_INT: expr = parser_parse_lint(parser); break; - case TOKEN_TYPE_EXPR_END: - parser_nxt_token(parser); + case TOKEN_TYPE_STR: + expr = parser_parse_lstr(parser); break; default: log_war("%s: Unknown token type: %d", __func__, parser->token->type); diff --git a/test/include/test.h b/test/include/test.h index 02c3d18..3193c52 100644 --- a/test/include/test.h +++ b/test/include/test.h @@ -3,6 +3,10 @@ #include "../../src/include/util.h" +/* + This is probably how it's supposed to work. In what other cases would you + need `extern`? +*/ extern unsigned int TESTS_RUN; extern unsigned int TESTS_PASSED; @@ -11,8 +15,8 @@ extern unsigned int TESTS_PASSED; #define ASSERT(EXPR) \ TESTS_RUN++; \ (EXPR && ++TESTS_PASSED) ? \ - log_inf("%s:%s:%d: Assertion passed!", __func__, __FILE__, __LINE__) : \ - log_err("%s:%s:%d: Assertion failed:\n\t%s", __func__, __FILE__, __LINE__, #EXPR); + log_inf("%s:%s:%d: Assertion passed!", __FILE__, __func__, __LINE__) : \ + log_err("%s:%s:%d: Assertion failed:\n\t%s", __FILE__, __func__, __LINE__, #EXPR); #define TEST_REPORT \ (TESTS_RUN == TESTS_PASSED) ? \ diff --git a/test/parser.c b/test/parser.c index 2007e93..feb9c70 100644 --- a/test/parser.c +++ b/test/parser.c @@ -6,13 +6,17 @@ TEST_INIT -void test_simple_empty() { +void empty() { + /* + Hmm… I feel as though this setup/cleanup process could be wrapped in a + macro. Tentative TODO? + */ tree_t* tree; pp_t* pp; lexer_t* lexer; parser_t* parser; - char src[] = " "; + char src[] = ""; /* @@ -32,6 +36,7 @@ void test_simple_empty() { ASSERT(tree_cmp(parser->tree, tree) == 1); + /* Probably not cleaning up fully here. Whatever. */ token_destroy(lexer->tokenl); lexer_destroy(lexer); pp_destroy(pp); @@ -39,7 +44,7 @@ void test_simple_empty() { parser_destroy(parser); } -void test_single_lint() { +void single_lint() { tree_t* tree; pp_t* pp; lexer_t* lexer; @@ -82,7 +87,7 @@ void test_single_lint() { parser_destroy(parser); } -void test_double_lint() { +void double_lint() { tree_t* tree; pp_t* pp; lexer_t* lexer; @@ -134,10 +139,164 @@ void test_double_lint() { parser_destroy(parser); } +void single_lstr() { + tree_t* tree; + pp_t* pp; + lexer_t* lexer; + parser_t* parser; + + char src[] = "\"Hello, World.\""; + + /* + + [block] + val: + [lstr] + val: + "Hello, World." + len: + 13 + nxt: + NULL + + */ + + tree = tree_init(TREE_TYPE_BLOCK); + tree_t* tree0lstr = tree->data.block.val = tree_init(TREE_TYPE_LSTR); + tree0lstr->data.lstr.val = "Hello, World."; + tree0lstr->data.lstr.len = 13; + tree->data.block.nxt = NULL; + + pp = pp_init(src); + pp_run(pp); + + lexer = lexer_init(pp->psrc); + lexer_run(lexer); + + parser = parser_init(lexer->tokenl); + parser_run(parser); + + ASSERT(tree_cmp(parser->tree, tree) == 1); + + token_destroy(lexer->tokenl); + lexer_destroy(lexer); + pp_destroy(pp); + tree_destroy(parser->tree); + parser_destroy(parser); +} + +void double_lstr() { + tree_t* tree; + pp_t* pp; + lexer_t* lexer; + parser_t* parser; + + char src[] = "\"foo\";\"bar\""; + + /* + + [block] + val: + [lstr] + val: + "foo" + len: + 3 + nxt: + [block] + val: + [lstr] + val: + "bar" + len: + 3 + nxt: + NULL + + */ + + tree = tree_init(TREE_TYPE_BLOCK); + tree_t* tree0lstr = tree->data.block.val = tree_init(TREE_TYPE_LSTR); + tree0lstr->data.lstr.val = "foo"; + tree0lstr->data.lstr.len = 3; + tree_t* tree0block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK); + tree_t* tree1lstr = tree0block->data.block.val = tree_init(TREE_TYPE_LSTR); + tree1lstr->data.lstr.val = "bar"; + tree1lstr->data.lstr.len = 3; + tree0block->data.block.nxt = NULL; + + pp = pp_init(src); + pp_run(pp); + + lexer = lexer_init(pp->psrc); + lexer_run(lexer); + + parser = parser_init(lexer->tokenl); + parser_run(parser); + + ASSERT(tree_cmp(parser->tree, tree) == 1); + + token_destroy(lexer->tokenl); + lexer_destroy(lexer); + pp_destroy(pp); + tree_destroy(parser->tree); + parser_destroy(parser); +} + +void single_block() { + tree_t* tree; + pp_t* pp; + lexer_t* lexer; + parser_t* parser; + + char src[] = "{}"; + + /* + + [block] + val: + [block] + val: + NULL + nxt: + NULL + nxt: + NULL + + */ + + tree = tree_init(TREE_TYPE_BLOCK); + tree_t* tree0block = tree->data.block.val = tree_init(TREE_TYPE_BLOCK); + tree0block->data.block.val = NULL; + tree0block->data.block.nxt = NULL; + tree->data.block.nxt = NULL; + + + pp = pp_init(src); + pp_run(pp); + + lexer = lexer_init(pp->psrc); + lexer_run(lexer); + + parser = parser_init(lexer->tokenl); + parser_run(parser); + + ASSERT(tree_cmp(parser->tree, tree) == 1); + + token_destroy(lexer->tokenl); + lexer_destroy(lexer); + pp_destroy(pp); + tree_destroy(parser->tree); + parser_destroy(parser); +} + int main(int argc, char** argv) { - test_simple_empty(); - test_single_lint(); - test_double_lint(); + empty(); + single_lint(); + double_lint(); + single_lstr(); + double_lstr(); + single_block(); TEST_REPORT; diff --git a/test/tree.c b/test/tree.c index 1b2742c..b9ef210 100644 --- a/test/tree.c +++ b/test/tree.c @@ -3,12 +3,17 @@ #include "../src/include/lexer.h" #include "../src/include/tree.h" -unsigned int TESTS_RUN = 0, TESTS_PASSED = 0; +TEST_INIT -int main(int argc, char** argv) { +/* + I wrote these before I started putting tests in their own functions, so + this'll have to do for now. +*/ +void test_things() { tree_t* tree_0; tree_t* tree_1; + /* Not refactoring this. */ tree_t* tree_lint_0; tree_t* tree_lint_1; tree_t* tree_lstr_0; @@ -240,7 +245,10 @@ int main(int argc, char** argv) { ASSERT(tree_cmp(tree_block_0, tree_block_0) == 1); ASSERT(tree_cmp(tree_block_0, tree_block_1) == 0); +} + +int main() { + test_things(); - TEST_REPORT; - return 0; + TEST_REPORT } -- cgit v1.2.3