Float literals are working

This commit is contained in:
Kyler Olsen 2025-11-17 21:53:25 -07:00
parent 204a819b52
commit 77b43b9595
4 changed files with 69 additions and 16 deletions

View File

@ -4,3 +4,4 @@ This is a list of things defined as currently in the specification, but not incl
- Unicode support - Unicode support
- Exponential literals - Exponential literals
- Arrays

View File

@ -263,7 +263,7 @@ static uint64_t create_decimal_integer(LexerInfo *lexer_info, size_t start) {
} }
for (; i < lexer_info->pos - start; i++) { for (; i < lexer_info->pos - start; i++) {
if (isspace(token[i]) || token[i] == '/' || token[i] == '\0' || token[i] == ':') break; if (isspace(token[i]) || token[i] == '/' || token[i] == '\0' || token[i] == ':') break;
if (token[i] == '.' || token[i] == '_') continue; if (token[i] == '_') continue;
value *= 10; value *= 10;
switch (token[i]) { switch (token[i]) {
case '1': value += 1; break; case '1': value += 1; break;
@ -366,6 +366,49 @@ static LexerResult create_integer_token(LexerInfo *lexer_info, IntegerBuiltInTyp
return lexer_result(lexer_info, (Token){TOKEN_INTEGER, .integer_literal = (IntegerLiteral){.type = type, .value = value}}, start, start_line); return lexer_result(lexer_info, (Token){TOKEN_INTEGER, .integer_literal = (IntegerLiteral){.type = type, .value = value}}, start, start_line);
} }
static double create_float(LexerInfo *lexer_info, size_t start) {
double value = 0;
Boolean negative = FALSE;
uint64_t fractional = 0;
const char *token = get_token_text(lexer_info, start);
size_t i = 0;
if (token[0] == '-') {
negative = TRUE;
i += 1;
}
for (; i < lexer_info->pos - start; i++) {
if (isspace(token[i]) || token[i] == '/' || token[i] == '\0' || token[i] == ':') break;
if (token[i] == '_') continue;
if (token[i] == '.') {
fractional = 1;
continue;
}
if (fractional == 0) value *= 10;
else fractional *= 10;
switch (token[i]) {
case '1': value += 1.0 / (fractional == 0 ? 1 : fractional); break;
case '2': value += 2.0 / (fractional == 0 ? 1 : fractional); break;
case '3': value += 3.0 / (fractional == 0 ? 1 : fractional); break;
case '4': value += 4.0 / (fractional == 0 ? 1 : fractional); break;
case '5': value += 5.0 / (fractional == 0 ? 1 : fractional); break;
case '6': value += 6.0 / (fractional == 0 ? 1 : fractional); break;
case '7': value += 7.0 / (fractional == 0 ? 1 : fractional); break;
case '8': value += 8.0 / (fractional == 0 ? 1 : fractional); break;
case '9': value += 9.0 / (fractional == 0 ? 1 : fractional); break;
}
}
if (negative) value = -value;
return value;
}
static LexerResult create_float_token(LexerInfo *lexer_info, NumericTypes type, size_t start, size_t start_line) {
double value = create_float(lexer_info, start);
if (type == NUMERIC_F64)
return lexer_result(lexer_info, (Token){TOKEN_DOUBLE, .double_literal = value}, start, start_line);
else
return lexer_result(lexer_info, (Token){TOKEN_FLOAT, .float_literal = (float){value}}, start, start_line);
}
typedef enum { typedef enum {
NUMERIC_BINARY, NUMERIC_BINARY,
NUMERIC_OCTAL, NUMERIC_OCTAL,
@ -450,7 +493,7 @@ static LexerResult parse_numeric_type(LexerInfo *lexer_info, char c, size_t star
value = create_hexadecimal_integer(lexer_info, start); value = create_hexadecimal_integer(lexer_info, start);
return create_integer_token(lexer_info, integer_type.integer_type, value, start, start_line); return create_integer_token(lexer_info, integer_type.integer_type, value, start, start_line);
case NUMERIC_FLOAT: case NUMERIC_FLOAT:
break; return create_float_token(lexer_info, numeric_type, start, start_line);
case NUMERIC_EXPONENTIAL: case NUMERIC_EXPONENTIAL:
break; break;
} }
@ -491,14 +534,22 @@ static LexerResult parse_exponential(LexerInfo *lexer_info, char c, size_t start
} }
static LexerResult parse_float(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { static LexerResult parse_float(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
(void)lexer_info; (void)c; (void)start; (void)start_line; while (isdigit(c) || c == '_') c = advance(lexer_info);
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Float Not Implemented Error."), 1}}; if (c == 'e' || c == 'E') return parse_exponential(lexer_info, c, start, start_line);
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_FLOAT);
if (isspace(c) || c == '/' || c == '\0')
return create_float_token(lexer_info, NUMERIC_F64, start, start_line);
SlsStr error_msg = sls_format(SLS_STR("Invalid float literal: unexpected '%c' in float literal."), 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_decimal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { static LexerResult parse_decimal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) {
while (isdigit(c) || c == '_') c = advance(lexer_info); while (isdigit(c) || c == '_') c = advance(lexer_info);
if (c == '.') return parse_float(lexer_info, c, start, start_line); if (c == '.') {
if (c == 'e' || c == 'E') return parse_exponential(lexer_info, c, start, start_line); c = advance(lexer_info);
return parse_float(lexer_info, c, start, start_line);
} if (c == 'e' || c == 'E') return parse_exponential(lexer_info, c, start, start_line);
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_DECIMAL); if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_DECIMAL);
if (isspace(c) || c == '/' || c == '\0') { if (isspace(c) || c == '/' || c == '\0') {
uint64_t value = create_decimal_integer(lexer_info, start); uint64_t value = create_decimal_integer(lexer_info, start);
@ -588,7 +639,8 @@ static LexerResult lexer_next(LexerInfo *lexer_info) {
// End of file tokens // End of file tokens
if (c == '\0') return lexer_result(lexer_info, (Token){.type = TOKEN_EOF}, start, start_line); if (c == '\0') return lexer_result(lexer_info, (Token){.type = TOKEN_EOF}, start, start_line);
// Integers and Floats // Integers and Floats
if (isdigit(c) || c == '.' || (c == '-' && isdigit(far_peek(lexer_info, 1)))) return parse_numeric_literal(lexer_info, c, start, start_line); if (isdigit(c) || (c == '.' && isdigit(far_peek(lexer_info, 1))) || (c == '-' && isdigit(far_peek(lexer_info, 1))))
return parse_numeric_literal(lexer_info, c, start, start_line);
// Character Literals // Character Literals
if (c == '\'') return parse_character_literal(lexer_info, c, start, start_line); if (c == '\'') return parse_character_literal(lexer_info, c, start, start_line);
// String Literals // String Literals

View File

@ -61,14 +61,14 @@ TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message)
} }
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); 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 = sls_str_cpy(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); if (test->result.error.message.str == NULL) return error_test_out_of_mem(test);
return test->result; return test->result;
} }
@ -319,8 +319,8 @@ Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double
LexerTokenResult *head = get_token(result.result, i); LexerTokenResult *head = get_token(result.result, i);
if (test_token_type(test, result, i, token_type)) { if (test_token_type(test, result, i, token_type)) {
return TRUE; return TRUE;
} if (fabs(head->result.float_literal - *value) >= FLOAT_TEST_PRECISION) { } if (fabs(head->result.double_literal - *value) >= FLOAT_TEST_PRECISION) {
logic_fail_test(test, result, float_value_should_be(i + 1, *value, head->result.float_literal)); logic_fail_test(test, result, float_value_should_be(i + 1, *value, head->result.double_literal));
return TRUE; return TRUE;
} }
return FALSE; return FALSE;

View File

@ -10,7 +10,7 @@
#include "sls/errors.h" #include "sls/errors.h"
#include "tests/tests.h" #include "tests/tests.h"
static const Boolean PRINT_SUCCESSFUL_TESTS = FALSE; static const Boolean PRINT_SUCCESSFUL_TESTS = TRUE;
const SlsStr TEST_FILE_NAME = SLS_STR("TEST_FILE.SLS"); const SlsStr TEST_FILE_NAME = SLS_STR("TEST_FILE.SLS");