diff --git a/SLS_C/Implementation Mismatches.md b/SLS_C/Implementation Mismatches.md index ad286e8..d00c08b 100644 --- a/SLS_C/Implementation Mismatches.md +++ b/SLS_C/Implementation Mismatches.md @@ -4,3 +4,4 @@ This is a list of things defined as currently in the specification, but not incl - Unicode support - Exponential literals +- Arrays diff --git a/SLS_C/src/lexer.c b/SLS_C/src/lexer.c index 99e55bf..352072e 100644 --- a/SLS_C/src/lexer.c +++ b/SLS_C/src/lexer.c @@ -263,7 +263,7 @@ static uint64_t create_decimal_integer(LexerInfo *lexer_info, size_t start) { } for (; i < lexer_info->pos - start; i++) { if (isspace(token[i]) || token[i] == '/' || token[i] == '\0' || token[i] == ':') break; - if (token[i] == '.' || token[i] == '_') continue; + if (token[i] == '_') continue; value *= 10; switch (token[i]) { 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); } +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 { NUMERIC_BINARY, 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); return create_integer_token(lexer_info, integer_type.integer_type, value, start, start_line); case NUMERIC_FLOAT: - break; + return create_float_token(lexer_info, numeric_type, start, start_line); case NUMERIC_EXPONENTIAL: 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 (isspace(c) || c == '/' || c == '\0') { 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); 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 (isspace(c) || c == '/' || c == '\0') { 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); 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) { - (void)lexer_info; (void)c; (void)start; (void)start_line; - return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Float Not Implemented Error."), 1}}; + while (isdigit(c) || c == '_') c = advance(lexer_info); + 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) { while (isdigit(c) || c == '_') c = advance(lexer_info); - if (c == '.') 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 == '.') { + 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 (isspace(c) || c == '/' || c == '\0') { 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); 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 (isspace(c) || c == '/' || c == '\0') { 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); 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 if (c == '\0') return lexer_result(lexer_info, (Token){.type = TOKEN_EOF}, start, start_line); // 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 if (c == '\'') return parse_character_literal(lexer_info, c, start, start_line); // String Literals diff --git a/SLS_C/tests/lexer_test_helpers.c b/SLS_C/tests/lexer_test_helpers.c index 4c121af..c2a7bf8 100644 --- a/SLS_C/tests/lexer_test_helpers.c +++ b/SLS_C/tests/lexer_test_helpers.c @@ -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) { - 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.error = error; 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; } @@ -319,8 +319,8 @@ Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double LexerTokenResult *head = get_token(result.result, i); if (test_token_type(test, result, i, token_type)) { return TRUE; - } if (fabs(head->result.float_literal - *value) >= FLOAT_TEST_PRECISION) { - logic_fail_test(test, result, float_value_should_be(i + 1, *value, head->result.float_literal)); + } if (fabs(head->result.double_literal - *value) >= FLOAT_TEST_PRECISION) { + logic_fail_test(test, result, float_value_should_be(i + 1, *value, head->result.double_literal)); return TRUE; } return FALSE; diff --git a/SLS_C/tests/tests.c b/SLS_C/tests/tests.c index bae2c24..e0f5c92 100644 --- a/SLS_C/tests/tests.c +++ b/SLS_C/tests/tests.c @@ -10,7 +10,7 @@ #include "sls/errors.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");