From 771069455d7191bc40b5bcf7927a546b75f323da Mon Sep 17 00:00:00 2001 From: LaEntropiaa Date: Mon, 9 Mar 2026 09:06:06 -0600 Subject: [PATCH] First version for string_to_number, just one test, is working fine, i'm considering swithching to handling only integers for in the future to manage in special struct that manages doubles as fractions, obviously this will mean changing nodes for general numbers to integers/fractions and shit --- include/lexer.h | 4 +++- src/lexer.c | 51 ++++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 7 ++++++ test/test_ASTNodeArray.c | 8 ++++++- test/test_lexer.c | 27 +++++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 test/test_lexer.c diff --git a/include/lexer.h b/include/lexer.h index d87441c..eccf1dc 100644 --- a/include/lexer.h +++ b/include/lexer.h @@ -34,6 +34,7 @@ typedef enum { LEXER_EMPTY_INPUT, LEXER_NULL_ARG, LEXER_WRONG_SYNTAX, + LEXER_BUF_OVERFLOW, } LexerErr; // Can be thought as tokens, they will be used by the parser. @@ -68,6 +69,7 @@ size_t ASTNodeArray_len(ASTNodeArray *arr); // Lexer funtions as well as few functionality LexerErr tokenize(const char* input, ASTNodeArray *out); LexerErr tokenize_number(const char* input, size_t *offset, ASTNode *out); -LexerErr string_to_number(const char* str, double *number); +LexerErr string_to_number(const char* input, size_t *offset, double *number); +void reverser_string(char* input); #endif // !LEXER_H diff --git a/src/lexer.c b/src/lexer.c index 859ff93..b0abbb8 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,6 +1,10 @@ #include "lexer.h" +#include +#include +#include #include #include +#include #define NODE_ARRAY_DEFAULT_SIZE 64 // Helps state machine for the lexer :) @@ -78,6 +82,16 @@ ASTNodeArrayErr ASTNodeArray_pop(ASTNodeArray *arr, size_t index, ASTNode *out) if (index >= arr->len) { return ARRAY_OUT_OF_BOUNDS; } + + if (arr->cap / 4 > arr->len) { + size_t new_cap = arr->cap / 2; + ASTNode *tmp = realloc(arr->data, new_cap * sizeof(ASTNode)); + if (tmp == NULL) { + return ARRAY_ALLOC; + } + arr->data = tmp; + arr->cap = new_cap; + } if (out != NULL) { ASTNode node_to_delete = arr->data[index]; @@ -97,3 +111,40 @@ size_t ASTNodeArray_len(ASTNodeArray *arr) { } return arr->len; } + +// CURRENTLY, it only supports ints, not clear how floating +// point is implemented but i'll figure it out +LexerErr string_to_number(const char *input, size_t *offset, double *number) { + char buf[128] = { '\0' }; + size_t buf_pos = 0; + + size_t current = *offset; + while (isdigit(input[current])) { + buf[buf_pos] = input[current]; + + if (buf_pos >= sizeof(buf)) { + return LEXER_BUF_OVERFLOW; + } + current++; + buf_pos++; + } + + int c = 0; + long count = 0; + while (buf[c] != '\0') { + + int digit = buf[c] - '0'; + + if (count > (INT_MAX - digit) / 10) { + return LEXER_FAILED_NUMBER_CONVERSION; + } + count = count * 10; + count += digit; + + c++; + } + + *number = (double) count; + *offset = current; + return LEXER_OK; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 99aff45..3aad9e4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,10 +1,17 @@ find_package(cmocka REQUIRED) add_executable(test_nodeArray test_ASTNodeArray.c) +add_executable(test_lexer test_lexer.c) target_link_libraries(test_nodeArray calculator_lib cmocka::cmocka ) +target_link_libraries(test_lexer + calculator_lib + cmocka::cmocka +) + add_test(NAME nodeArray_tests COMMAND test_nodeArray) +add_test(NAME lexer_tests COMMAND test_lexer) diff --git a/test/test_ASTNodeArray.c b/test/test_ASTNodeArray.c index 6d81a97..cc28297 100644 --- a/test/test_ASTNodeArray.c +++ b/test/test_ASTNodeArray.c @@ -34,12 +34,15 @@ static void test_array_push(void **state) { assert_int_equal(ASTNodeArray_push(&arr, node3), ARRAY_OK); assert_int_equal(ASTNodeArray_len(&arr), 3); + + ASTNodeArray_free(&arr); } static void test_array_pop(void **state) { (void) state; - ASTNodeArray arr = ASTNodeArray_init(2); + // Set to force desize + ASTNodeArray arr = ASTNodeArray_init(16); ASTNode node1 = { .type = NODE_NUMBER, .data = { .number = 90 } @@ -68,8 +71,11 @@ static void test_array_pop(void **state) { assert_int_equal(ASTNodeArray_pop(&arr, 1, &node4), ARRAY_OK); assert_int_equal(node4.type, NODE_NUMBER); assert_int_equal(node4.data.number, 80); + + ASTNodeArray_free(&arr); } + int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_array_push), diff --git a/test/test_lexer.c b/test/test_lexer.c new file mode 100644 index 0000000..8d59e72 --- /dev/null +++ b/test/test_lexer.c @@ -0,0 +1,27 @@ +#include "lexer.h" +#include +#include +#include +#include +#include +#include + +static void test_string_to_number(void **state) { + (void) state; + + char num[16] = "2333t55"; + size_t offset = 0; + double result = 0; + assert_int_equal(string_to_number(num, &offset, &result), 0); + + assert_int_equal(offset, 4); + assert_double_equal(result, 2333, 1e-6); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_string_to_number), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}