summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorCarlos Maniero <carlosmaniero@gmail.com>2023-04-25 03:52:59 -0300
committerJohnny Richard <johnny@johnnyrichard.com>2023-04-25 22:54:22 +0200
commitc1a1bd2320b4c1508c4ab20d23b7c193a94d8026 (patch)
treeea54aa17ba0223b9ff58087bdcb6af778186702e /test
parentcca2c345f9b16b88e1fc4e9ea598cf2f7ed8653a (diff)
parser: Add support for variables and identifiers in function body
This commit adds support for variables and identifiers in the function body of the parser, stored as a vector. However, at this point, identifier resolution is not fully implemented, and we currently accept identifiers without checking if they can be resolved. This is a known limitation that will be addressed in a future commit once hash-tables are added to the parser. Signed-off-by: Carlos Maniero <carlosmaniero@gmail.com> Reviewed-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'test')
-rw-r--r--test/Makefile2
-rw-r--r--test/lexer_test.c1
-rw-r--r--test/parser_test.c56
3 files changed, 54 insertions, 5 deletions
diff --git a/test/Makefile b/test/Makefile
index 09adcfb..40f5cf9 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -23,7 +23,7 @@ vector_test: munit.o ../build/vector.o vector_test.o
lexer_test: munit.o ../build/string_view.o ../build/lexer.o lexer_test.o
$(CC) $? $(CFLAGS) -o $@
-parser_test: munit.o ../build/string_view.o ../build/lexer.o ../build/ast.o ../build/parser.o parser_test.o
+parser_test: munit.o ../build/string_view.o ../build/vector.o ../build/lexer.o ../build/ast.o ../build/parser.o parser_test.o
$(CC) $? $(CFLAGS) -o $@
integration_test: munit.o integration_test.o
diff --git a/test/lexer_test.c b/test/lexer_test.c
index ae713b3..0eebfe5 100644
--- a/test/lexer_test.c
+++ b/test/lexer_test.c
@@ -71,6 +71,7 @@ test_tokenize_op(const MunitParameter params[],
assert_token_at(" - \n", 0, TOKEN_OP, "-");
assert_token_at(" * ;", 0, TOKEN_OP, "*");
assert_token_at(" / ", 0, TOKEN_OP, "/");
+ assert_token_at(" = ", 0, TOKEN_OP, "=");
assert_token_at("1 * 2", 0, TOKEN_NUMBER, "1");
assert_token_at("1 * 2", 1, TOKEN_OP, "*");
diff --git a/test/parser_test.c b/test/parser_test.c
index 2e73fa6..daa2fe7 100644
--- a/test/parser_test.c
+++ b/test/parser_test.c
@@ -15,11 +15,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define MUNIT_ENABLE_ASSERT_ALIASES
-#include "munit.h"
+#include "ast.h"
#include "lexer.h"
+#include "munit.h"
#include "parser.h"
-#include "ast.h"
#include "string.h"
+#include "vector.h"
void assert_string_view_equal(char *expected, string_view_t actual);
@@ -49,6 +50,8 @@ assert_parser_error(char* src, char* error_msg) {
assert_false(parsed);
assert_int(1, ==, parser.errors_len);
assert_string_equal(error_msg, parser.errors[0].message);
+
+ ast_node_destroy(ast_function);
}
static MunitResult
@@ -71,7 +74,7 @@ test_parse_function(const MunitParameter params[],
assert_string_equal("main", actual);
assert_int(AST_FUNCTION_DECLARATION, ==, ast_function->kind);
- ast_node_t *ast_return = ast_function->data.function.body;
+ ast_node_t *ast_return = vector_at(ast_function->data.function.body, 0);
assert_int(AST_RETURN_STMT, ==, ast_return->kind);
@@ -86,6 +89,46 @@ test_parse_function(const MunitParameter params[],
}
static MunitResult
+test_parse_variable_definition(const MunitParameter params[],
+ void *user_data_or_fixture)
+{
+ parser_t parser;
+ lexer_t lexer;
+
+ make_lexer_from_static_src(&lexer, "main(): i32 { \nvariable : i32 = 42; \nreturn variable;\n }");
+ parser_init(&parser, &lexer);
+ ast_node_t *ast_function = ast_node_new();
+
+ bool parsed = parser_parse_function_declaration(&parser, ast_function);
+
+ assert_true(parsed);
+
+ char actual[5];
+
+ string_view_to_str(&ast_function->data.function.name, actual);
+ assert_string_equal("main", actual);
+ assert_int(AST_FUNCTION_DECLARATION, ==, ast_function->kind);
+
+ ast_node_t *ast_variable = vector_at(ast_function->data.function.body, 0);
+
+ assert_int(AST_VARIABLE_DECLARATION, ==, ast_variable->kind);
+ assert_string_view_equal("variable", ast_variable->data.variable.name);
+
+ ast_node_t *ast_return = vector_at(ast_function->data.function.body, 1);
+
+ assert_int(AST_RETURN_STMT, ==, ast_return->kind);
+
+ ast_node_t *ast_literal = ast_return->data.return_stmt.argument;
+
+ assert_int(AST_IDENTIFIER, ==, ast_literal->kind);
+ assert_string_view_equal("variable", ast_literal->data.identifier.name);
+
+ ast_node_destroy(ast_function);
+
+ return MUNIT_OK;
+}
+
+static MunitResult
test_parse_arithmetic_expression(const MunitParameter params[],
void *user_data_or_fixture)
{
@@ -167,15 +210,20 @@ test_parse_basic_syntax_errors(const MunitParameter params[],
assert_parser_error("main(): i32 { return; }" , "unexpected '; (;)' token");
assert_parser_error("main(): i32 { return 42;" , "expected '}' but got end of file");
assert_parser_error("main(): beff { return 42; }" , "type 'beff' is not defined");
- assert_parser_error("main(): i32 { oxi 42; }" , "expected 'return' keyword but got 'oxi'");
+ // FIXME: once function calls are implemented, this error should inform that
+ // neither a variable or function call was found.
+ assert_parser_error("main(): i32 { oxi 42; }" , "expected ':' but got 'TOKEN_NUMBER'");
return MUNIT_OK;
}
static MunitTest tests[] = {
{ "/test_parse_function", test_parse_function, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
+ { "/test_parse_function", test_parse_function, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
{ "/test_parse_basic_syntax_errors", test_parse_basic_syntax_errors, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
{ "/test_parse_arithmetic_expression", test_parse_arithmetic_expression, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
+ { "/test_parse_arithmetic_expression", test_parse_arithmetic_expression, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
+ { "/test_parse_variable_definition", test_parse_variable_definition, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
};