From e25975e29d4b4ac4561664e52a2e757f271ccddc Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sun, 10 Aug 2025 16:39:13 +0100 Subject: [PATCH] Create read module --- lib/CMakeLists.txt | 1 + lib/include/read.h | 9 ++++ lib/read.c | 22 ++++++++++ tests/CMakeLists.txt | 1 + tests/read_tests.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 lib/include/read.h create mode 100644 lib/read.c create mode 100644 tests/read_tests.c diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 1e95c07..2e57449 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(imp parse.c prim.c print.c + read.c store.c token.c ) diff --git a/lib/include/read.h b/lib/include/read.h new file mode 100644 index 0000000..289131b --- /dev/null +++ b/lib/include/read.h @@ -0,0 +1,9 @@ +#ifndef READ_H +#define READ_H + +#include "am.h" +#include "stream.h" + +void read(am_t *am, stream_t *stream); + +#endif diff --git a/lib/read.c b/lib/read.c new file mode 100644 index 0000000..1840c89 --- /dev/null +++ b/lib/read.c @@ -0,0 +1,22 @@ +#include "read.h" + +#include "parse.h" +#include "token.h" + +#include + +void read(am_t *am, stream_t *stream) +{ + parse_ctx_t ctx; + token_t token; + + parse_init(am, &ctx); + + while (ctx.state != PARSE_STATE_DONE) { + const token_status_t token_status = token_read(stream, &token); + assert(token_status == TOKEN_OK); + + parse_proc(&ctx, &token); + assert(ctx.state != PARSE_STATE_ERROR); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8d5f3a7..409973f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,6 +16,7 @@ add_test_suites( parse_tests.c prim_tests.c print_tests.c + read_tests.c store_tests.c token_tests.c ) diff --git a/tests/read_tests.c b/tests/read_tests.c new file mode 100644 index 0000000..67af1f6 --- /dev/null +++ b/tests/read_tests.c @@ -0,0 +1,98 @@ +#include "memory_stream.h" +#include "read.h" +#include "unity.h" + +#include + +#define CAR(expr) (expr->pair.car) +#define CDR(expr) (expr->pair.cdr) +#define CADR(expr) CAR(CDR(expr)) +#define CDDR(expr) CDR(CDR(expr)) +#define CADDR(expr) CAR(CDDR(expr)) +#define CDDDR(expr) CDR(CDDR(expr)) +#define CAADDR(expr) CAR(CADDR(expr)) +#define CDADDR(expr) CDR(CADDR(expr)) +#define CADADDR(expr) CAR(CDADDR(expr)) +#define CDDADDR(expr) CDR(CDADDR(expr)) +#define CADDADDR(expr) CAR(CDDADDR(expr)) +#define CDDDADDR(expr) CDR(CDDADDR(expr)) + +static am_t am; + +void setUp(void) +{ + am_init(&am); +} + +void tearDown(void) +{ +} + +static void test_nested_expression(void) +{ + const char *input = "(+ 1 (* 2 3))"; + memory_stream_t stream; + memory_stream_init(&stream, (const uint8_t *)input, strlen(input)); + + read(&am, (stream_t *)&stream); + + TEST_ASSERT_NOT_NULL(am.expr); + TEST_ASSERT_FALSE(am.expr->is_atom); + + TEST_ASSERT_NOT_NULL(CAR(am.expr)); + TEST_ASSERT_TRUE(CAR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_SYMBOL, CAR(am.expr)->atom.type); + TEST_ASSERT_EQUAL(1, CAR(am.expr)->atom.symbol.len); + TEST_ASSERT_EQUAL_MEMORY("+", CAR(am.expr)->atom.symbol.buf, 1); + + TEST_ASSERT_NOT_NULL(CDR(am.expr)); + TEST_ASSERT_FALSE(CDR(am.expr)->is_atom); + + TEST_ASSERT_NOT_NULL(CADR(am.expr)); + TEST_ASSERT_TRUE(CADR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, CADR(am.expr)->atom.type); + TEST_ASSERT_EQUAL(1, CADR(am.expr)->atom.integer); + + TEST_ASSERT_NOT_NULL(CDDR(am.expr)); + TEST_ASSERT_FALSE(CDDR(am.expr)->is_atom); + + TEST_ASSERT_NOT_NULL(CADDR(am.expr)); + TEST_ASSERT_FALSE(CADDR(am.expr)->is_atom); + + TEST_ASSERT_NOT_NULL(CAADDR(am.expr)); + TEST_ASSERT_TRUE(CAADDR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_SYMBOL, CAADDR(am.expr)->atom.type); + TEST_ASSERT_EQUAL(1, CAADDR(am.expr)->atom.symbol.len); + TEST_ASSERT_EQUAL_MEMORY("*", CAADDR(am.expr)->atom.symbol.buf, 1); + + TEST_ASSERT_NOT_NULL(CDADDR(am.expr)); + TEST_ASSERT_FALSE(CDADDR(am.expr)->is_atom); + + TEST_ASSERT_NOT_NULL(CADADDR(am.expr)); + TEST_ASSERT_TRUE(CADADDR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, CADADDR(am.expr)->atom.type); + TEST_ASSERT_EQUAL(2, CADADDR(am.expr)->atom.integer); + + TEST_ASSERT_NOT_NULL(CDDADDR(am.expr)); + TEST_ASSERT_FALSE(CDDADDR(am.expr)->is_atom); + + TEST_ASSERT_NOT_NULL(CADDADDR(am.expr)); + TEST_ASSERT_TRUE(CADDADDR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, CADDADDR(am.expr)->atom.type); + TEST_ASSERT_EQUAL(3, CADDADDR(am.expr)->atom.integer); + + TEST_ASSERT_NOT_NULL(CDDDADDR(am.expr)); + TEST_ASSERT_TRUE(CDDDADDR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_EMPTY_LIST, CDDDADDR(am.expr)->atom.type); + + TEST_ASSERT_NOT_NULL(CDDDR(am.expr)); + TEST_ASSERT_TRUE(CDDDR(am.expr)->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_EMPTY_LIST, CDDDR(am.expr)->atom.type); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_nested_expression); + return UNITY_END(); +}