Float literals are working
This commit is contained in:
parent
204a819b52
commit
77b43b9595
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -466,7 +509,7 @@ static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t st
|
||||||
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_BINARY);
|
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_BINARY);
|
||||||
if (isspace(c) || c == '/' || c == '\0') {
|
if (isspace(c) || c == '/' || c == '\0') {
|
||||||
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);
|
||||||
}
|
}
|
||||||
SlsStr error_msg = sls_format(SLS_STR("Invalid binary literal: unexpected '%c' in binary integer."), c);
|
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}};
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
|
@ -478,7 +521,7 @@ static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t sta
|
||||||
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_OCTAL);
|
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_OCTAL);
|
||||||
if (isspace(c) || c == '/' || c == '\0') {
|
if (isspace(c) || c == '/' || c == '\0') {
|
||||||
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);
|
||||||
}
|
}
|
||||||
SlsStr error_msg = sls_format(SLS_STR("Invalid octal literal: unexpected '%c' in octal integer."), c);
|
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}};
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
|
@ -491,18 +534,26 @@ 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);
|
||||||
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line);
|
||||||
}
|
}
|
||||||
SlsStr error_msg = sls_format(SLS_STR("Invalid decimal literal: unexpected '%c' in decimal integer."), c);
|
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}};
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
|
@ -514,7 +565,7 @@ static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size
|
||||||
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_HEXADECIMAL);
|
if (c == ':') return parse_numeric_type(lexer_info, c, start, start_line, NUMERIC_HEXADECIMAL);
|
||||||
if (isspace(c) || c == '/' || c == '\0') {
|
if (isspace(c) || c == '/' || c == '\0') {
|
||||||
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);
|
||||||
}
|
}
|
||||||
SlsStr error_msg = sls_format(SLS_STR("Invalid hexadecimal literal: unexpected '%c' in hexadecimal integer."), c);
|
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}};
|
if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}};
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue