Refactor string handling functions
This commit is contained in:
parent
2b44aad1c7
commit
beae4f0b9d
|
|
@ -7,26 +7,27 @@
|
||||||
#define SLS_STRING_H
|
#define SLS_STRING_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "bool.h"
|
#include "bool.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t len;
|
size_t len; // Number of useable characters (does not include trailing null character)
|
||||||
const char *str;
|
char *str;
|
||||||
Boolean allocated;
|
Boolean allocated;
|
||||||
} SlsStr;
|
} SlsStr;
|
||||||
|
|
||||||
#define SLS_STR(s) (SlsStr){ sizeof(s) - 1, (s), FALSE }
|
#define SLS_STR(s) (SlsStr){ sizeof(s) - 1, (s), FALSE }
|
||||||
|
#define SLS_STR_NULL (SlsStr){0, NULL, FALSE}
|
||||||
|
|
||||||
int isascii(unsigned char c);
|
int sls_isascii(unsigned char c);
|
||||||
size_t strnlen(const char *s, size_t maxlen);
|
size_t sls_str_nlen(const char *s, size_t maxlen);
|
||||||
|
SlsStr sls_str_malloc(const char *s, size_t maxlen);
|
||||||
SlsStr malloc_str(const char *s, size_t maxlen);
|
SlsStr sls_str_new(size_t length);
|
||||||
SlsStr new_str(size_t length);
|
SlsStr sls_str_cpy(SlsStr s);
|
||||||
SlsStr copy_str(SlsStr s);
|
int32_t sls_str_cmp(SlsStr a, SlsStr b);
|
||||||
int32_t compare_str(SlsStr a, SlsStr b);
|
void sls_str_free(SlsStr *s);
|
||||||
void free_str(SlsStr *s);
|
SlsStr sls_format(const SlsStr s, ...);
|
||||||
SlsStr format(const SlsStr s, ...);
|
|
||||||
|
|
||||||
#endif // SLS_STRING_H
|
#endif // SLS_STRING_H
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ typedef struct {
|
||||||
|
|
||||||
LexerTest start_up_test(SlsStr test_name, SlsStr test_code);
|
LexerTest start_up_test(SlsStr test_name, SlsStr test_code);
|
||||||
void clean_up_test(LexerResult result);
|
void clean_up_test(LexerResult result);
|
||||||
|
TestResult error_test_out_of_mem(LexerTest *test);
|
||||||
TestResult error_test(LexerTest *test, LexerResult result, SlsError error);
|
TestResult error_test(LexerTest *test, LexerResult result, SlsError error);
|
||||||
TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message);
|
TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message);
|
||||||
TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error);
|
TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error);
|
||||||
|
|
|
||||||
|
|
@ -454,7 +454,9 @@ static LexerResult parse_numeric_type(LexerInfo *lexer_info, char c, size_t star
|
||||||
}
|
}
|
||||||
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Numeric Literal Not Implemented Error."), 1}};
|
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Numeric Literal Not Implemented Error."), 1}};
|
||||||
}
|
}
|
||||||
return lexer_error(lexer_info, format(SLS_STR("Invalid numeric literal: unexpected '%c' in numeric type."), c), start, start_line);
|
SlsStr error_msg = sls_format(SLS_STR("Invalid numeric literal: unexpected '%c' in numeric type."), c);
|
||||||
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
return lexer_error(lexer_info, error_msg, start, start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
||||||
|
|
@ -464,7 +466,9 @@ static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t st
|
||||||
uint64_t value = create_binary_integer(lexer_info, start);
|
uint64_t value = create_binary_integer(lexer_info, start);
|
||||||
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
||||||
}
|
}
|
||||||
return lexer_error(lexer_info, format(SLS_STR("Invalid binary literal: unexpected '%c' in binary integer."), c), start, start_line);
|
SlsStr error_msg = sls_format(SLS_STR("Invalid binary literal: unexpected '%c' in binary integer."), c);
|
||||||
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
return lexer_error(lexer_info, error_msg, start, start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
||||||
|
|
@ -474,7 +478,9 @@ static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t sta
|
||||||
uint64_t value = create_octal_integer(lexer_info, start);
|
uint64_t value = create_octal_integer(lexer_info, start);
|
||||||
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
||||||
}
|
}
|
||||||
return lexer_error(lexer_info, format(SLS_STR("Invalid octal literal: unexpected '%c' in octal integer."), c), start, start_line);
|
SlsStr error_msg = sls_format(SLS_STR("Invalid octal literal: unexpected '%c' in octal integer."), c);
|
||||||
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
return lexer_error(lexer_info, error_msg, start, start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LexerResult parse_exponential(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
static LexerResult parse_exponential(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
||||||
|
|
@ -496,7 +502,9 @@ static LexerResult parse_decimal_integer(LexerInfo *lexer_info, char c, size_t s
|
||||||
uint64_t value = create_decimal_integer(lexer_info, start);
|
uint64_t value = create_decimal_integer(lexer_info, start);
|
||||||
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
||||||
}
|
}
|
||||||
return lexer_error(lexer_info, format(SLS_STR("Invalid decimal literal: unexpected '%c' in decimal integer."), c), start, start_line);
|
SlsStr error_msg = sls_format(SLS_STR("Invalid decimal literal: unexpected '%c' in decimal integer."), c);
|
||||||
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
return lexer_error(lexer_info, error_msg, start, start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
||||||
|
|
@ -506,7 +514,9 @@ static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size
|
||||||
uint64_t value = create_hexadecimal_integer(lexer_info, start);
|
uint64_t value = create_hexadecimal_integer(lexer_info, start);
|
||||||
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
||||||
}
|
}
|
||||||
return lexer_error(lexer_info, format(SLS_STR("Invalid hexadecimal literal: unexpected '%c' in hexadecimal integer."), c), start, start_line);
|
SlsStr error_msg = sls_format(SLS_STR("Invalid hexadecimal literal: unexpected '%c' in hexadecimal integer."), c);
|
||||||
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
return lexer_error(lexer_info, error_msg, start, start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LexerResult parse_numeric_literal(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
static LexerResult parse_numeric_literal(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
|
||||||
|
|
@ -588,7 +598,7 @@ static LexerResult lexer_next(LexerInfo *lexer_info) {
|
||||||
// Type Tuples
|
// Type Tuples
|
||||||
if (c == '(') return parse_type_tuples(lexer_info, c, start, start_line);
|
if (c == '(') return parse_type_tuples(lexer_info, c, start, start_line);
|
||||||
// Identifiers and Booleans
|
// Identifiers and Booleans
|
||||||
if (isascii(c)) return parse_identifiers_and_booleans(lexer_info, c, start, start_line);
|
if (sls_isascii(c)) return parse_identifiers_and_booleans(lexer_info, c, start, start_line);
|
||||||
// Lexing Error
|
// Lexing Error
|
||||||
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Unknown Character Error."), 1}};
|
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Unknown Character Error."), 1}};
|
||||||
}
|
}
|
||||||
|
|
@ -598,9 +608,9 @@ void clean_token_result(LexerTokenResult *head) {
|
||||||
LexerTokenResult *next;
|
LexerTokenResult *next;
|
||||||
while (head) {
|
while (head) {
|
||||||
next = head->next;
|
next = head->next;
|
||||||
if (head->type == SLS_ERROR) free_str(&head->error.message);
|
if (head->type == SLS_ERROR) sls_str_free(&head->error.message);
|
||||||
else {
|
else {
|
||||||
if (head->result.type == TOKEN_STRING) free_str(&head->error.message);
|
if (head->result.type == TOKEN_STRING) sls_str_free(&head->error.message);
|
||||||
}
|
}
|
||||||
if (head) free(head);
|
if (head) free(head);
|
||||||
head = next;
|
head = next;
|
||||||
|
|
|
||||||
|
|
@ -14,48 +14,53 @@
|
||||||
#include "sls/string.h"
|
#include "sls/string.h"
|
||||||
#include "sls/lexer.h"
|
#include "sls/lexer.h"
|
||||||
|
|
||||||
int isascii(unsigned char c) {
|
int sls_isascii(unsigned char c) {
|
||||||
return c < 128;
|
return c < 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t strnlen(const char *s, size_t maxlen) {
|
size_t sls_str_nlen(const char *s, size_t maxlen) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < maxlen; i++)
|
for (i = 0; i < maxlen; i++)
|
||||||
if (s[i] == '\0') break;
|
if (s[i] == '\0') break;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlsStr malloc_str(const char *s, size_t maxlen) {
|
SlsStr sls_str_malloc(const char *s, size_t maxlen) {
|
||||||
size_t length = strnlen(s, maxlen);
|
size_t length = sls_str_nlen(s, maxlen);
|
||||||
char *new_str = (char *)malloc(sizeof(char) * (length + 1));
|
char *new_str = (char *)malloc(sizeof(char) * (length + 1));
|
||||||
strncpy(new_str, s, length + 1);
|
if (new_str == NULL) return SLS_STR_NULL;
|
||||||
|
memcpy(new_str, s, length);
|
||||||
|
new_str[length] = '\0';
|
||||||
return (SlsStr){length, new_str, TRUE};
|
return (SlsStr){length, new_str, TRUE};
|
||||||
}
|
}
|
||||||
|
|
||||||
SlsStr new_str(size_t length) {
|
SlsStr sls_str_new(size_t length) {
|
||||||
char *new_str = (char *)malloc(sizeof(char) * length);
|
char *new_str = (char *)calloc(length + 1, sizeof(char));
|
||||||
for (size_t i = 0; i < length; i++) new_str[i] = '\0';
|
if (new_str == NULL) return SLS_STR_NULL;
|
||||||
return (SlsStr){length, new_str, TRUE};
|
return (SlsStr){length, new_str, TRUE};
|
||||||
}
|
}
|
||||||
|
|
||||||
SlsStr copy_str(SlsStr s) {
|
SlsStr sls_str_cpy(const SlsStr s) {
|
||||||
return malloc_str(s.str, s.len);
|
return sls_str_malloc(s.str, s.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compare_str(SlsStr a, SlsStr b) {
|
int32_t sls_str_cmp(const SlsStr a, const SlsStr b) {
|
||||||
return strcmp(a.str, b.str);
|
int cmp = strncmp(a.str, b.str, (a.len < b.len) ? a.len : b.len);
|
||||||
|
if (cmp != 0) return cmp;
|
||||||
|
return (a.len > b.len) - (a.len < b.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_str(SlsStr *s) {
|
void sls_str_free(SlsStr *s) {
|
||||||
if (s->allocated) {
|
if (s->allocated) {
|
||||||
free((void *)s->str);
|
free((void *)s->str);
|
||||||
s->len = 0;
|
s->len = 0;
|
||||||
s->str = 0;
|
s->str = NULL;
|
||||||
s->allocated = FALSE;
|
s->allocated = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
FORMAT_PERCENT_ESCAPE,
|
||||||
FORMAT_C_STRINGS,
|
FORMAT_C_STRINGS,
|
||||||
FORMAT_CHARACTER,
|
FORMAT_CHARACTER,
|
||||||
FORMAT_INTEGER_32,
|
FORMAT_INTEGER_32,
|
||||||
|
|
@ -88,27 +93,34 @@ typedef struct {
|
||||||
SlsError error;
|
SlsError error;
|
||||||
Boolean boolean;
|
Boolean boolean;
|
||||||
};
|
};
|
||||||
size_t str_index;
|
ptrdiff_t str_index;
|
||||||
size_t self_length;
|
size_t self_length;
|
||||||
} FormatStringItem;
|
} FormatStringItem;
|
||||||
|
|
||||||
static size_t number_length(int64_t i) {
|
static size_t number_length(int64_t i) {
|
||||||
if (i == 0) return 1;
|
if (i == 0) return 1;
|
||||||
else return (i < 0 ? 1 : 0) + (int)log10(llabs(i) + 1);
|
size_t len = (i < 0 ? 1 : 0);
|
||||||
|
while (i) { len++; i /= 10; }
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t unsigned_number_length(uint64_t i) {
|
static size_t unsigned_number_length(uint64_t i) {
|
||||||
if (i == 0) return 1;
|
if (i == 0) return 1;
|
||||||
else return (int)log10(i + 1);
|
size_t len = 0;
|
||||||
|
while (i) { len++; i /= 10; }
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlsStr format(const SlsStr s, ...) {
|
SlsStr sls_format(const SlsStr s, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, s);
|
va_start(args, s);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
const char *current = strchr(s.str, '%');
|
const char *current = strchr(s.str, '%');
|
||||||
do {
|
do {
|
||||||
|
if (!current) break;
|
||||||
|
if (!current[1]) break;
|
||||||
switch (current[1]) {
|
switch (current[1]) {
|
||||||
|
case '%':
|
||||||
case 'y':
|
case 'y':
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'd':
|
case 'd':
|
||||||
|
|
@ -129,121 +141,119 @@ SlsStr format(const SlsStr s, ...) {
|
||||||
} while (current);
|
} while (current);
|
||||||
|
|
||||||
FormatStringItem *items = (FormatStringItem *)malloc(sizeof(FormatStringItem) * count);
|
FormatStringItem *items = (FormatStringItem *)malloc(sizeof(FormatStringItem) * count);
|
||||||
|
if (items == NULL) return SLS_STR_NULL;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t last_index = (size_t)s.str;
|
const char *last_index = s.str;
|
||||||
|
size_t length = s.len;
|
||||||
current = strchr(s.str, '%');
|
current = strchr(s.str, '%');
|
||||||
do {
|
do {
|
||||||
switch (current[1]) {
|
switch (current[1]) {
|
||||||
|
case '%':
|
||||||
|
items[i].type = FORMAT_PERCENT_ESCAPE;
|
||||||
|
length += items[i].self_length = 1;
|
||||||
|
length -= 2;
|
||||||
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
items[i].type = FORMAT_C_STRINGS;
|
items[i].type = FORMAT_C_STRINGS;
|
||||||
items[i].c_string = va_arg(args, const char *);
|
items[i].c_string = va_arg(args, const char *);
|
||||||
|
length += items[i].self_length = strlen(items[i].c_string);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
items[i].type = FORMAT_CHARACTER;
|
items[i].type = FORMAT_CHARACTER;
|
||||||
items[i].character = va_arg(args, int);
|
items[i].character = va_arg(args, int);
|
||||||
|
length += items[i].self_length = 1;
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
items[i].type = FORMAT_INTEGER_32;
|
items[i].type = FORMAT_INTEGER_32;
|
||||||
items[i].integer_32 = va_arg(args, int32_t);
|
items[i].integer_32 = va_arg(args, int32_t);
|
||||||
|
length += items[i].self_length = number_length(items[i].integer_32);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
items[i].type = FORMAT_INTEGER_64;
|
items[i].type = FORMAT_INTEGER_64;
|
||||||
items[i].integer_64 = va_arg(args, int64_t);
|
items[i].integer_64 = va_arg(args, int64_t);
|
||||||
|
length += items[i].self_length = number_length(items[i].integer_64);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
items[i].type = FORMAT_UNSIGNED_INTEGER_64;
|
items[i].type = FORMAT_UNSIGNED_INTEGER_64;
|
||||||
items[i].unsigned_integer_64 = va_arg(args, uint64_t);
|
items[i].unsigned_integer_64 = va_arg(args, uint64_t);
|
||||||
|
length += items[i].self_length = unsigned_number_length(items[i].unsigned_integer_64);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
items[i].type = FORMAT_SIZE_INTEGER;
|
items[i].type = FORMAT_SIZE_INTEGER;
|
||||||
items[i].size_integer = va_arg(args, size_t);
|
items[i].size_integer = va_arg(args, size_t);
|
||||||
|
length += items[i].self_length = unsigned_number_length(items[i].size_integer);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
items[i].type = FORMAT_FLOAT;
|
items[i].type = FORMAT_FLOAT;
|
||||||
items[i].ffloat = va_arg(args, double);
|
items[i].ffloat = va_arg(args, double);
|
||||||
|
length += items[i].self_length = snprintf(NULL, 0, "%.2f", items[i].ffloat);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
items[i].type = FORMAT_SLS_STR;
|
items[i].type = FORMAT_SLS_STR;
|
||||||
items[i].sls_str = va_arg(args, SlsStr);
|
items[i].sls_str = va_arg(args, SlsStr);
|
||||||
|
length += items[i].self_length = items[i].sls_str.len;
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
items[i].type = FORMAT_SLS_TOKEN_TYPE;
|
items[i].type = FORMAT_SLS_TOKEN_TYPE;
|
||||||
items[i].token_type = va_arg(args, TokenType);
|
items[i].token_type = va_arg(args, TokenType);
|
||||||
|
length += items[i].self_length = sls_str_nlen(TOKEN_TYPES_NAMES[items[i].token_type], TYPE_NAMES_SAFE_LENGTH);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
items[i].type = FORMAT_SLS_ARRAY_TYPE;
|
items[i].type = FORMAT_SLS_ARRAY_TYPE;
|
||||||
items[i].array_type = va_arg(args, ArrayType);
|
items[i].array_type = va_arg(args, ArrayType);
|
||||||
|
length += items[i].self_length = sls_str_nlen(ARRAY_TYPES_NAMES[items[i].array_type], TYPE_NAMES_SAFE_LENGTH);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
items[i].type = FORMAT_SLS_BUILTIN_INTEGER;
|
items[i].type = FORMAT_SLS_BUILTIN_INTEGER;
|
||||||
items[i].builtin_integer = va_arg(args, IntegerBuiltInType);
|
items[i].builtin_integer = va_arg(args, IntegerBuiltInType);
|
||||||
|
length += items[i].self_length = sls_str_nlen(INTEGER_TYPES_NAMES[items[i].builtin_integer], TYPE_NAMES_SAFE_LENGTH);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
items[i].type = FORMAT_SLS_ERROR;
|
items[i].type = FORMAT_SLS_ERROR;
|
||||||
items[i].error = va_arg(args, SlsError);
|
items[i].error = va_arg(args, SlsError);
|
||||||
|
length += items[i].self_length = items[i].error.message.len;
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
items[i].type = FORMAT_SLS_BOOLEAN;
|
items[i].type = FORMAT_SLS_BOOLEAN;
|
||||||
items[i].boolean = va_arg(args, Boolean);
|
items[i].boolean = va_arg(args, Boolean);
|
||||||
|
length += items[i].self_length = (items[i].boolean ? 4 : 5);
|
||||||
|
length -= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
items[i].str_index = (size_t)current - last_index;
|
items[i].str_index = (ptrdiff_t)(current - last_index);
|
||||||
last_index = (size_t)current + 2;
|
last_index = current + 2;
|
||||||
i++;
|
i++;
|
||||||
current = strchr(current + 2, '%');
|
current = strchr(current + 2, '%');
|
||||||
} while (current);
|
} while (current);
|
||||||
|
va_end(args);
|
||||||
size_t length = s.len - (count * 2);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
switch (items[i].type) {
|
|
||||||
case FORMAT_C_STRINGS:
|
|
||||||
length += items[i].self_length = strlen(items[i].c_string);
|
|
||||||
break;
|
|
||||||
case FORMAT_CHARACTER:
|
|
||||||
length += items[i].self_length = 1;
|
|
||||||
break;
|
|
||||||
case FORMAT_INTEGER_32:
|
|
||||||
length += items[i].self_length = number_length(items[i].integer_32);
|
|
||||||
break;
|
|
||||||
case FORMAT_INTEGER_64:
|
|
||||||
length += items[i].self_length = number_length(items[i].integer_64);
|
|
||||||
break;
|
|
||||||
case FORMAT_UNSIGNED_INTEGER_64:
|
|
||||||
length += items[i].self_length = unsigned_number_length(items[i].unsigned_integer_64);
|
|
||||||
break;
|
|
||||||
case FORMAT_SIZE_INTEGER:
|
|
||||||
length += items[i].self_length = unsigned_number_length(items[i].size_integer);
|
|
||||||
break;
|
|
||||||
case FORMAT_FLOAT:
|
|
||||||
length += items[i].self_length = number_length(items[i].ffloat) + 3;
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_STR:
|
|
||||||
length += items[i].self_length = items[i].sls_str.len - 1;
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_TOKEN_TYPE:
|
|
||||||
length += items[i].self_length = strnlen(TOKEN_TYPES_NAMES[items[i].token_type], TYPE_NAMES_SAFE_LENGTH);
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_ARRAY_TYPE:
|
|
||||||
length += items[i].self_length = strnlen(ARRAY_TYPES_NAMES[items[i].array_type], TYPE_NAMES_SAFE_LENGTH);
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_BUILTIN_INTEGER:
|
|
||||||
length += items[i].self_length = strnlen(INTEGER_TYPES_NAMES[items[i].builtin_integer], TYPE_NAMES_SAFE_LENGTH);
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_ERROR:
|
|
||||||
length += items[i].self_length = items[i].error.message.len - 1;
|
|
||||||
break;
|
|
||||||
case FORMAT_SLS_BOOLEAN:
|
|
||||||
length += items[i].self_length = (items[i].boolean ? 4 : 5);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *temp = (char *)malloc(sizeof(char) * length);
|
char *temp = (char *)malloc(sizeof(char) * length);
|
||||||
SlsStr str_new = new_str(length);
|
if (temp == NULL) {
|
||||||
|
free(items);
|
||||||
|
return SLS_STR_NULL;
|
||||||
|
}
|
||||||
|
SlsStr str_new = sls_str_new(length);
|
||||||
|
if (str_new.str == NULL) {
|
||||||
|
free(items);
|
||||||
|
free(temp);
|
||||||
|
return SLS_STR_NULL;
|
||||||
|
}
|
||||||
char *str = (char *)str_new.str;
|
char *str = (char *)str_new.str;
|
||||||
size_t item_i = 0;
|
size_t item_i = 0;
|
||||||
size_t target_i = 0;
|
ptrdiff_t target_i = 0;
|
||||||
size_t source_i = 0;
|
ptrdiff_t source_i = 0;
|
||||||
|
|
||||||
while (item_i < count) {
|
while (item_i < count) {
|
||||||
memcpy(str + target_i, s.str + source_i, items[item_i].str_index);
|
memcpy(str + target_i, s.str + source_i, items[item_i].str_index);
|
||||||
|
|
@ -251,6 +261,9 @@ SlsStr format(const SlsStr s, ...) {
|
||||||
source_i += items[item_i].str_index + 2;
|
source_i += items[item_i].str_index + 2;
|
||||||
|
|
||||||
switch (items[item_i].type) {
|
switch (items[item_i].type) {
|
||||||
|
case FORMAT_PERCENT_ESCAPE:
|
||||||
|
memcpy(temp, "%", items[item_i].self_length + 1);
|
||||||
|
break;
|
||||||
case FORMAT_C_STRINGS:
|
case FORMAT_C_STRINGS:
|
||||||
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].c_string);
|
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].c_string);
|
||||||
break;
|
break;
|
||||||
|
|
@ -270,7 +283,7 @@ SlsStr format(const SlsStr s, ...) {
|
||||||
snprintf(temp, items[item_i].self_length + 1, "%zu", items[item_i].size_integer);
|
snprintf(temp, items[item_i].self_length + 1, "%zu", items[item_i].size_integer);
|
||||||
break;
|
break;
|
||||||
case FORMAT_FLOAT:
|
case FORMAT_FLOAT:
|
||||||
snprintf(temp, items[item_i].self_length + 1, "%.2f", items[item_i].ffloat);
|
snprintf(temp, items[item_i].self_length + 1, "%.2f", items[item_i].ffloat); // Fixed-point decimal display
|
||||||
break;
|
break;
|
||||||
case FORMAT_SLS_STR:
|
case FORMAT_SLS_STR:
|
||||||
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].sls_str.str);
|
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].sls_str.str);
|
||||||
|
|
@ -288,8 +301,7 @@ SlsStr format(const SlsStr s, ...) {
|
||||||
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].error.message.str);
|
snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].error.message.str);
|
||||||
break;
|
break;
|
||||||
case FORMAT_SLS_BOOLEAN:
|
case FORMAT_SLS_BOOLEAN:
|
||||||
if (items[item_i].boolean) memcpy(temp, "TRUE", 5);
|
memcpy(temp, (items[item_i].boolean ? "TRUE" : "FALSE"), items[item_i].self_length + 1);
|
||||||
else memcpy(temp, "FALSE", 6);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,7 +309,9 @@ SlsStr format(const SlsStr s, ...) {
|
||||||
target_i += items[item_i].self_length;
|
target_i += items[item_i].self_length;
|
||||||
item_i++;
|
item_i++;
|
||||||
}
|
}
|
||||||
memcpy(str + target_i, s.str + source_i, s.len - source_i);
|
if (s.len > source_i)
|
||||||
|
memcpy(str + target_i, s.str + source_i, s.len - source_i);
|
||||||
|
str[str_new.len] = '\0';
|
||||||
|
|
||||||
free(items);
|
free(items);
|
||||||
free(temp);
|
free(temp);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
#include "tests/lexer_test_helpers.h"
|
#include "tests/lexer_test_helpers.h"
|
||||||
#include "tests/tests.h"
|
#include "tests/tests.h"
|
||||||
|
|
||||||
static const double FLOAT_TEST_PRECISION = 0.01;
|
static const double FLOAT_TEST_PRECISION = 0.0078125;
|
||||||
|
|
||||||
// Test start and end helpers
|
// Test start and end helpers
|
||||||
|
|
||||||
|
|
@ -33,43 +33,63 @@ void clean_up_test(LexerResult result) {
|
||||||
clean_token_result(result.result);
|
clean_token_result(result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult error_test_out_of_mem(LexerTest *test) {
|
||||||
|
test->result.status = TEST_ERROR;
|
||||||
|
test->result.error = (SlsError){SLS_STR("Out Of Memory Error."), 1};
|
||||||
|
return test->result;
|
||||||
|
}
|
||||||
|
|
||||||
TestResult error_test(LexerTest *test, LexerResult result, SlsError error) {
|
TestResult error_test(LexerTest *test, LexerResult result, SlsError error) {
|
||||||
|
clean_up_test(result);
|
||||||
|
|
||||||
|
if (error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
|
|
||||||
test->result.status = TEST_ERROR;
|
test->result.status = TEST_ERROR;
|
||||||
test->result.error = error;
|
test->result.error = error;
|
||||||
test->result.error.message = copy_str(error.message);
|
test->result.error.message = sls_str_cpy(error.message);
|
||||||
|
|
||||||
clean_up_test(result);
|
if (test->result.error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message) {
|
TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message) {
|
||||||
|
clean_up_test(result);
|
||||||
|
|
||||||
test->result.status = TEST_LOGIC_FAIL;
|
test->result.status = TEST_LOGIC_FAIL;
|
||||||
test->result.message = message;
|
test->result.message = message;
|
||||||
clean_up_test(result);
|
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult logic_error_fail_test(LexerTest *test, LexerResult result, SlsError error) {
|
TestResult logic_error_fail_test(LexerTest *test, LexerResult result, SlsError error) {
|
||||||
|
clean_up_test(result);
|
||||||
|
|
||||||
|
if (error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
|
|
||||||
test->result.status = TEST_LOGIC_ERROR_FAIL;
|
test->result.status = TEST_LOGIC_ERROR_FAIL;
|
||||||
test->result.error = error;
|
test->result.error = error;
|
||||||
test->result.error.message = copy_str(error.message);
|
test->result.error.message = sls_str_cpy(error.message);
|
||||||
|
|
||||||
clean_up_test(result);
|
if (test->result.error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error) {
|
TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error) {
|
||||||
|
clean_up_test(result);
|
||||||
|
|
||||||
|
if (error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
|
|
||||||
test->result.status = TEST_ERROR_FAIL;
|
test->result.status = TEST_ERROR_FAIL;
|
||||||
test->result.error = error;
|
test->result.error = error;
|
||||||
test->result.error.message = copy_str(error.message);
|
test->result.error.message = sls_str_cpy(error.message);
|
||||||
|
|
||||||
clean_up_test(result);
|
if (test->result.error.message.str == NULL) return error_test_out_of_mem(test);
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult skip_test(LexerTest *test, LexerResult result) {
|
TestResult skip_test(LexerTest *test, LexerResult result) {
|
||||||
test->result.status = TEST_NOT_IMPLEMENTED;
|
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
|
|
||||||
|
test->result.status = TEST_NOT_IMPLEMENTED;
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,106 +99,107 @@ TestResult skip_test_no_result(LexerTest *test) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult pass_test(LexerTest *test, LexerResult result) {
|
TestResult pass_test(LexerTest *test, LexerResult result) {
|
||||||
test->result.status = TEST_PASS;
|
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
|
|
||||||
|
test->result.status = TEST_PASS;
|
||||||
return test->result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test messages
|
// Test messages
|
||||||
|
|
||||||
static SlsStr unexpected_end_of_token_stream(size_t i) {
|
static SlsStr unexpected_end_of_token_stream(size_t i) {
|
||||||
return format(SLS_STR("Unexpected end of token stream (%z tokens found)"), i - 1);
|
return sls_format(SLS_STR("Unexpected end of token stream (%z tokens found)"), i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr expected_end_of_token_stream(size_t i) {
|
static SlsStr expected_end_of_token_stream(size_t i) {
|
||||||
return format(SLS_STR("Expected end of token stream (more than %z tokens found)"), i - 1);
|
return sls_format(SLS_STR("Expected end of token stream (more than %z tokens found)"), i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr token_should_be(size_t i, TokenType should, TokenType found) {
|
static SlsStr token_should_be(size_t i, TokenType should, TokenType found) {
|
||||||
return format(SLS_STR("Token #%z should be a %t, but found a %t"), i, should, found);
|
return sls_format(SLS_STR("Token #%z should be a %t, but found a %t"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr integer_type_should_be(size_t i, IntegerBuiltInType should, IntegerBuiltInType found) {
|
static SlsStr integer_type_should_be(size_t i, IntegerBuiltInType should, IntegerBuiltInType found) {
|
||||||
return format(SLS_STR("Token #%z integer type should be a %i, but found a %i"), i, should, found);
|
return sls_format(SLS_STR("Token #%z integer type should be a %i, but found a %i"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr integer_value_should_be(size_t i, uint64_t should, uint64_t found) {
|
static SlsStr integer_value_should_be(size_t i, uint64_t should, uint64_t found) {
|
||||||
return format(SLS_STR("Token #%z integer value should be %i, but found %i"), i, should, found);
|
return sls_format(SLS_STR("Token #%z integer value should be %i, but found %i"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr float_value_should_be(size_t i, double should, double found) {
|
static SlsStr float_value_should_be(size_t i, double should, double found) {
|
||||||
return format(SLS_STR("Token #%z float value should be %f, but found %f"), i, should, found);
|
return sls_format(SLS_STR("Token #%z float value should be %f, but found %f"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr identifier_should_be_literal(size_t i) {
|
static SlsStr identifier_should_be_literal(size_t i) {
|
||||||
return format(SLS_STR("Token #%z identifier should be an identifier literal"), i);
|
return sls_format(SLS_STR("Token #%z identifier should be an identifier literal"), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr identifier_should_not_be_literal(size_t i) {
|
static SlsStr identifier_should_not_be_literal(size_t i) {
|
||||||
return format(SLS_STR("Token #%z identifier should not be an identifier literal"), i);
|
return sls_format(SLS_STR("Token #%z identifier should not be an identifier literal"), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr token_length_should_be(size_t i, TokenType type, uint64_t should, uint64_t found) {
|
static SlsStr token_length_should_be(size_t i, TokenType type, uint64_t should, uint64_t found) {
|
||||||
return format(SLS_STR("Token #%z of type %t length should be %u, but found %u"), i, type, should, found);
|
return sls_format(SLS_STR("Token #%z of type %t length should be %u, but found %u"), i, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr token_value_string_should_be(size_t i, TokenType type, SlsStr should, SlsStr found) {
|
static SlsStr token_value_string_should_be(size_t i, TokenType type, SlsStr should, SlsStr found) {
|
||||||
return format(SLS_STR("Token #%z of type %t string value should be %s, but found %s"), i, type, should, found);
|
return sls_format(SLS_STR("Token #%z of type %t string value should be %s, but found %s"), i, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr boolean_should_be(size_t i, Boolean value) {
|
static SlsStr boolean_should_be(size_t i, Boolean value) {
|
||||||
if (value) return format(SLS_STR("Token #%z boolean should be true, but is false"), i);
|
if (value) return sls_format(SLS_STR("Token #%z boolean should be true, but is false"), i);
|
||||||
else return format(SLS_STR("Token #%z boolean should be false, but is true"), i);
|
else return sls_format(SLS_STR("Token #%z boolean should be false, but is true"), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_type_should_be(size_t i, ArrayType should, ArrayType found) {
|
static SlsStr array_type_should_be(size_t i, ArrayType should, ArrayType found) {
|
||||||
return format(SLS_STR("Token #%z should be a %a, but found a %a"), i, should, found);
|
return sls_format(SLS_STR("Token #%z should be a %a, but found a %a"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_dimensions_should_be(size_t i, size_t should, size_t found) {
|
static SlsStr array_dimensions_should_be(size_t i, size_t should, size_t found) {
|
||||||
return format(SLS_STR("Token #%z array dimensions should be %z, but found %z"), i, should, found);
|
return sls_format(SLS_STR("Token #%z array dimensions should be %z, but found %z"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_dimension_shape_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) {
|
static SlsStr array_dimension_shape_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) {
|
||||||
return format(SLS_STR("Token #%z dimension %z of array type %a should be shape %u, but found %u"), i, j, type, should, found);
|
return sls_format(SLS_STR("Token #%z dimension %z of array type %a should be shape %u, but found %u"), i, j, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_element_integer_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) {
|
static SlsStr array_element_integer_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) {
|
||||||
return format(SLS_STR("Token #%z element %z of array type %a should be %u, but found %u"), i, j, type, should, found);
|
return sls_format(SLS_STR("Token #%z element %z of array type %a should be %u, but found %u"), i, j, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_element_float_should_be(size_t i, size_t j, ArrayType type, double should, double found) {
|
static SlsStr array_element_float_should_be(size_t i, size_t j, ArrayType type, double should, double found) {
|
||||||
return format(SLS_STR("Token #%z element %z of array type %a should be %f, but found %f"), i, j, type, should, found);
|
return sls_format(SLS_STR("Token #%z element %z of array type %a should be %f, but found %f"), i, j, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_element_string_should_be(size_t i, size_t j, ArrayType type, SlsStr should, SlsStr found) {
|
static SlsStr array_element_string_should_be(size_t i, size_t j, ArrayType type, SlsStr should, SlsStr found) {
|
||||||
return format(SLS_STR("Token #%z element %z of array type %a should be %s, but found %s"), i, j, type, should, found);
|
return sls_format(SLS_STR("Token #%z element %z of array type %a should be %s, but found %s"), i, j, type, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr array_element_boolean_should_be(size_t i, size_t j, ArrayType type, Boolean value) {
|
static SlsStr array_element_boolean_should_be(size_t i, size_t j, ArrayType type, Boolean value) {
|
||||||
if (value) return format(SLS_STR("Token #%z element %z of array type %a should be true, but is false"), i, j, type);
|
if (value) return sls_format(SLS_STR("Token #%z element %z of array type %a should be true, but is false"), i, j, type);
|
||||||
else return format(SLS_STR("Token #%z element %z of array type %a should be false, but is true"), i, j, type);
|
else return sls_format(SLS_STR("Token #%z element %z of array type %a should be false, but is true"), i, j, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr type_tuple_element_integer_should_be(size_t i, size_t j, uint64_t should, uint64_t found) {
|
static SlsStr type_tuple_element_integer_should_be(size_t i, size_t j, uint64_t should, uint64_t found) {
|
||||||
return format(SLS_STR("Token #%z element %u of type tuple should be %u, but found %u"), i, j, should, found);
|
return sls_format(SLS_STR("Token #%z element %u of type tuple should be %u, but found %u"), i, j, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr type_tuple_element_string_should_be(size_t i, size_t j, SlsStr should, SlsStr found) {
|
static SlsStr type_tuple_element_string_should_be(size_t i, size_t j, SlsStr should, SlsStr found) {
|
||||||
return format(SLS_STR("Token #%z element %z of type tuple should be %s, but found %s"), i, j, should, found);
|
return sls_format(SLS_STR("Token #%z element %z of type tuple should be %s, but found %s"), i, j, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr type_tuple_element_boolean_should_be(size_t i, size_t j, Boolean value) {
|
static SlsStr type_tuple_element_boolean_should_be(size_t i, size_t j, Boolean value) {
|
||||||
if (value) return format(SLS_STR("Token #%z element %z of type tuple should be true, but is false"), i, j);
|
if (value) return sls_format(SLS_STR("Token #%z element %z of type tuple should be true, but is false"), i, j);
|
||||||
else return format(SLS_STR("Token #%z element %z of type tuple should be false, but is true"), i, j);
|
else return sls_format(SLS_STR("Token #%z element %z of type tuple should be false, but is true"), i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr token_should_be_error(size_t i, SlsStr should, TokenType found) {
|
static SlsStr token_should_be_error(size_t i, SlsStr should, TokenType found) {
|
||||||
return format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found token of type %t"), i, should, found);
|
return sls_format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found token of type %t"), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SlsStr error_should_be(size_t i, SlsStr should, SlsError found) {
|
static SlsStr error_should_be(size_t i, SlsStr should, SlsError found) {
|
||||||
return format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found error with message \"%e\""), i, should, found);
|
return sls_format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found error with message \"%e\""), i, should, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test parts
|
// Test parts
|
||||||
|
|
@ -242,7 +263,7 @@ Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, Tes
|
||||||
} if (head->result.identifier.name.len == value->name.len) {
|
} if (head->result.identifier.name.len == value->name.len) {
|
||||||
logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value->name.len, head->result.identifier.name.len));
|
logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value->name.len, head->result.identifier.name.len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.identifier.name, value->name) != 0) {
|
} if (sls_str_cmp(head->result.identifier.name, value->name) != 0) {
|
||||||
logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, head->result.identifier.name, value->name));
|
logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, head->result.identifier.name, value->name));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +317,7 @@ Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr
|
||||||
} if (head->result.string_literal.len == value.len) {
|
} if (head->result.string_literal.len == value.len) {
|
||||||
logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value.len, head->result.string_literal.len));
|
logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value.len, head->result.string_literal.len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.string_literal, value) != 0) {
|
} if (sls_str_cmp(head->result.string_literal, value) != 0) {
|
||||||
logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, value, head->result.string_literal));
|
logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, value, head->result.string_literal));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +348,7 @@ Boolean test_array_identifier_value(LexerTest *test, LexerResult result, size_t
|
||||||
if (head->result.array_literal.identifiers[j].name.len == values->values[j].name.len) {
|
if (head->result.array_literal.identifiers[j].name.len == values->values[j].name.len) {
|
||||||
logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].name.len, head->result.array_literal.identifiers[j].name.len));
|
logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].name.len, head->result.array_literal.identifiers[j].name.len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.array_literal.identifiers[j].name, values->values[j].name)) {
|
} if (sls_str_cmp(head->result.array_literal.identifiers[j].name, values->values[j].name)) {
|
||||||
logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j].name, head->result.array_literal.identifiers[j].name));
|
logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j].name, head->result.array_literal.identifiers[j].name));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.array_literal.identifiers[j].is_literal) {
|
} if (head->result.array_literal.identifiers[j].is_literal) {
|
||||||
|
|
@ -401,7 +422,7 @@ Boolean test_array_string_value(LexerTest *test, LexerResult result, size_t i, T
|
||||||
if (head->result.array_literal.string_literals[j].len == values->values[j].len) {
|
if (head->result.array_literal.string_literals[j].len == values->values[j].len) {
|
||||||
logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].len, head->result.array_literal.string_literals[j].len));
|
logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].len, head->result.array_literal.string_literals[j].len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.array_literal.string_literals[j], values->values[j])) {
|
} if (sls_str_cmp(head->result.array_literal.string_literals[j], values->values[j])) {
|
||||||
logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j], head->result.array_literal.string_literals[j]));
|
logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j], head->result.array_literal.string_literals[j]));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +452,7 @@ Boolean test_array_struct_inline_value(LexerTest *test, LexerResult result, size
|
||||||
LexerTokenResult *head = get_token(result.result, i);
|
LexerTokenResult *head = get_token(result.result, i);
|
||||||
if (test_array_type(test, result, i, array_type, values->shape, values->dimensions)) {
|
if (test_array_type(test, result, i, array_type, values->shape, values->dimensions)) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.array_literal.struct_inline.name, values->struct_name)) {
|
} if (sls_str_cmp(head->result.array_literal.struct_inline.name, values->struct_name)) {
|
||||||
logic_fail_test(test, result, token_value_string_should_be(i + 1, TOKEN_IDENTIFIER, values->struct_name, head->result.array_literal.struct_inline.name));
|
logic_fail_test(test, result, token_value_string_should_be(i + 1, TOKEN_IDENTIFIER, values->struct_name, head->result.array_literal.struct_inline.name));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -491,7 +512,7 @@ Boolean test_type_tuple_value(LexerTest *test, LexerResult result, size_t i, Tes
|
||||||
if (head->result.type_tuple.input_identifiers[j].name.len == values->input_values[j].name.len) {
|
if (head->result.type_tuple.input_identifiers[j].name.len == values->input_values[j].name.len) {
|
||||||
logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->input_values[j].name.len, head->result.type_tuple.input_identifiers[j].name.len));
|
logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->input_values[j].name.len, head->result.type_tuple.input_identifiers[j].name.len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.type_tuple.input_identifiers[j].name, values->input_values[j].name)) {
|
} if (sls_str_cmp(head->result.type_tuple.input_identifiers[j].name, values->input_values[j].name)) {
|
||||||
logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->input_values[j].name, head->result.type_tuple.input_identifiers[j].name));
|
logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->input_values[j].name, head->result.type_tuple.input_identifiers[j].name));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.type_tuple.input_identifiers[j].is_literal) {
|
} if (head->result.type_tuple.input_identifiers[j].is_literal) {
|
||||||
|
|
@ -502,7 +523,7 @@ Boolean test_type_tuple_value(LexerTest *test, LexerResult result, size_t i, Tes
|
||||||
if (head->result.type_tuple.output_identifiers[j].name.len == values->output_values[j].name.len) {
|
if (head->result.type_tuple.output_identifiers[j].name.len == values->output_values[j].name.len) {
|
||||||
logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->output_values[j].name.len, head->result.type_tuple.output_identifiers[j].name.len));
|
logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->output_values[j].name.len, head->result.type_tuple.output_identifiers[j].name.len));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->result.type_tuple.output_identifiers[j].name, values->output_values[j].name)) {
|
} if (sls_str_cmp(head->result.type_tuple.output_identifiers[j].name, values->output_values[j].name)) {
|
||||||
logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->output_values[j].name, head->result.type_tuple.output_identifiers[j].name));
|
logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->output_values[j].name, head->result.type_tuple.output_identifiers[j].name));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.type_tuple.output_identifiers[j].is_literal) {
|
} if (head->result.type_tuple.output_identifiers[j].is_literal) {
|
||||||
|
|
@ -518,7 +539,7 @@ Boolean test_for_error(LexerTest *test, LexerResult result, size_t i, SlsStr err
|
||||||
if (head->type != SLS_ERROR) {
|
if (head->type != SLS_ERROR) {
|
||||||
logic_fail_test(test, result, token_should_be_error(i + 1, error, head->result.type));
|
logic_fail_test(test, result, token_should_be_error(i + 1, error, head->result.type));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (compare_str(head->error.message, error) != 0) {
|
} if (sls_str_cmp(head->error.message, error) != 0) {
|
||||||
logic_fail_test(test, result, error_should_be(i + 1, error, head->error));
|
logic_fail_test(test, result, error_should_be(i + 1, error, head->error));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,13 @@ static void lexer_test_report(TestsReport reports, TestCounts *counts) {
|
||||||
// Red
|
// Red
|
||||||
printf("\x1b[31mTest failed with lexical error: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].error.message.str);
|
printf("\x1b[31mTest failed with lexical error: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].error.message.str);
|
||||||
counts->logic_error_failed += 1;
|
counts->logic_error_failed += 1;
|
||||||
free_str(&reports.tests[i].message);
|
sls_str_free(&reports.tests[i].message);
|
||||||
break;
|
break;
|
||||||
case TEST_LOGIC_FAIL:
|
case TEST_LOGIC_FAIL:
|
||||||
// Red
|
// Red
|
||||||
printf("\x1b[31mTest failed: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].message.str);
|
printf("\x1b[31mTest failed: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].message.str);
|
||||||
counts->logic_failed += 1;
|
counts->logic_failed += 1;
|
||||||
free_str(&reports.tests[i].message);
|
sls_str_free(&reports.tests[i].message);
|
||||||
break;
|
break;
|
||||||
case TEST_PASS:
|
case TEST_PASS:
|
||||||
// Green
|
// Green
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue