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

This commit is contained in:
2026-03-09 09:06:06 -06:00
parent 194f1dd80f
commit 771069455d
5 changed files with 95 additions and 2 deletions

View File

@@ -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

View File

@@ -1,6 +1,10 @@
#include "lexer.h"
#include <ctype.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <strings.h>
#include <limits.h>
#define NODE_ARRAY_DEFAULT_SIZE 64
// Helps state machine for the lexer :)
@@ -79,6 +83,16 @@ ASTNodeArrayErr ASTNodeArray_pop(ASTNodeArray *arr, size_t index, ASTNode *out)
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];
*out = node_to_delete;
@@ -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;
}

View File

@@ -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)

View File

@@ -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),

27
test/test_lexer.c Normal file
View File

@@ -0,0 +1,27 @@
#include "lexer.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
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);
}