White space breaks stuff, but other than that its good
This commit is contained in:
parent
f8894ea4c0
commit
f2033e30e9
|
|
@ -657,9 +657,48 @@ static LexerResult parse_type_tuples(LexerInfo *lexer_info, char c, size_t start
|
|||
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Type Tuples Not Implemented Error."), 1}};
|
||||
}
|
||||
|
||||
Boolean is_identifier_continue(LexerInfo *lexer_info, char c) {
|
||||
if (!isprint(c)) return FALSE;
|
||||
if (c == '/' && far_peek(lexer_info, 1) == '/') return FALSE;
|
||||
if (c == '{' || c == '}') return FALSE;
|
||||
if (c == '[' || c == ']') return FALSE;
|
||||
if (c == '(' || c == ')') return FALSE;
|
||||
if (c == '\'' || c == '"') return FALSE;
|
||||
if (c == '.' || c == ':' || c == '#') return FALSE;
|
||||
if (isspace(c) || c == '\0') return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Boolean is_identifier_start(LexerInfo *lexer_info, char c) {
|
||||
if (c == ':' && far_peek(lexer_info, 1) == ':') c = far_peek(lexer_info, 2);
|
||||
if ((!isdigit(c)) && is_identifier_continue(lexer_info, c)) return TRUE;
|
||||
else return FALSE;
|
||||
}
|
||||
|
||||
static LexerResult parse_identifiers_and_booleans(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: Identifiers and Booleans Not Implemented Error."), 1}};
|
||||
Boolean literal = FALSE;
|
||||
if (c == ':' && far_peek(lexer_info, 1) == ':') {
|
||||
literal = TRUE;
|
||||
c = advance(lexer_info);
|
||||
c = advance(lexer_info);
|
||||
}
|
||||
|
||||
size_t length = 0;
|
||||
while (is_identifier_continue(lexer_info, c)) {
|
||||
c = advance(lexer_info);
|
||||
length++;
|
||||
}
|
||||
char *name_value = (char *)calloc(length+1, sizeof(char));
|
||||
for (size_t i = 0; i < length; i++)
|
||||
name_value[i] = lexer_info->source_code.str[i + (2 * literal)];
|
||||
SlsStr name = sls_str_malloc(name_value, length);
|
||||
free(name_value);
|
||||
if (sls_str_cmp(name, SLS_STR("false")) == 0)
|
||||
return lexer_result(lexer_info, (Token){TOKEN_BOOLEAN, .boolean_literal = FALSE}, start, start_line);
|
||||
else if (sls_str_cmp(name, SLS_STR("true")) == 0)
|
||||
return lexer_result(lexer_info, (Token){TOKEN_BOOLEAN, .boolean_literal = TRUE}, start, start_line);
|
||||
else
|
||||
return lexer_result(lexer_info, (Token){TOKEN_IDENTIFIER, .identifier = (Identifier){.is_literal = literal, .name = name}}, start, start_line);
|
||||
}
|
||||
|
||||
static LexerResult lexer_next(LexerInfo *lexer_info) {
|
||||
|
|
@ -697,7 +736,8 @@ static LexerResult lexer_next(LexerInfo *lexer_info) {
|
|||
// Type Tuples
|
||||
if (c == '(') return parse_type_tuples(lexer_info, c, start, start_line);
|
||||
// Identifiers and Booleans
|
||||
if (sls_isascii(c)) return parse_identifiers_and_booleans(lexer_info, c, start, start_line);
|
||||
if (is_identifier_start(lexer_info, c))
|
||||
return parse_identifiers_and_booleans(lexer_info, c, start, start_line);
|
||||
// Lexing Error
|
||||
return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Unknown Character Error."), 1}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, Tes
|
|||
} if (head->result.identifier.is_literal != value->is_literal) {
|
||||
logic_fail_test(test, result, value->is_literal ? identifier_should_be_literal(i + 1) : identifier_should_not_be_literal(i + 1));
|
||||
return TRUE;
|
||||
} 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));
|
||||
return TRUE;
|
||||
} if (sls_str_cmp(head->result.identifier.name, value->name) != 0) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
1344
SLS_Tests/cases.yaml
1344
SLS_Tests/cases.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -63,6 +63,10 @@ class IdentifierTestGenerator(BaseTestGenerator):
|
|||
# All caps with underscores
|
||||
self.make_success_test("Identifier All Caps", "MY_CONSTANT",
|
||||
"identifier", "MY_CONSTANT")
|
||||
|
||||
# Others
|
||||
self.make_success_test("Identifier With Dash", "my-var",
|
||||
"identifier_literal", "my-var")
|
||||
|
||||
def generate_identifier_literal_tests(self):
|
||||
"""Generate identifier literal tests (with :: prefix)."""
|
||||
|
|
@ -113,7 +117,7 @@ class IdentifierTestGenerator(BaseTestGenerator):
|
|||
"identifier", "hello")
|
||||
self.make_success_test("Identifier Both Whitespace", " hello ",
|
||||
"identifier", "hello")
|
||||
self.make_success_test("Identifier Tab Before", "\thello",
|
||||
self.make_success_test("Identifier Tab Before", "\\thello",
|
||||
"identifier", "hello")
|
||||
|
||||
# Identifier literals with whitespace
|
||||
|
|
@ -146,17 +150,13 @@ class IdentifierTestGenerator(BaseTestGenerator):
|
|||
# Starting with number
|
||||
self.make_error_test("Identifier Starting With Number",
|
||||
"123abc",
|
||||
"Invalid identifier: cannot start with digit.")
|
||||
"Invalid decimal literal: unexpected 'a' in decimal integer.")
|
||||
|
||||
# Invalid characters
|
||||
self.make_error_test("Identifier With Hash",
|
||||
"my#var",
|
||||
"Invalid identifier: '#' is not allowed in identifiers.")
|
||||
|
||||
self.make_error_test("Identifier With Dash",
|
||||
"my-var",
|
||||
"Invalid identifier: '-' is not allowed in identifiers.")
|
||||
|
||||
self.make_error_test("Identifier With Dot",
|
||||
"my.var",
|
||||
"Invalid identifier: '.' is not allowed in identifiers.")
|
||||
|
|
@ -287,7 +287,7 @@ class BooleanTestGenerator(BaseTestGenerator):
|
|||
"bool", True)
|
||||
self.make_success_test("Bool True Both Whitespace", " true ",
|
||||
"bool", True)
|
||||
self.make_success_test("Bool True Tab Before", "\ttrue",
|
||||
self.make_success_test("Bool True Tab Before", "\\ttrue",
|
||||
"bool", True)
|
||||
|
||||
# False with whitespace
|
||||
|
|
@ -297,73 +297,57 @@ class BooleanTestGenerator(BaseTestGenerator):
|
|||
"bool", False)
|
||||
self.make_success_test("Bool False Both Whitespace", " false ",
|
||||
"bool", False)
|
||||
self.make_success_test("Bool False Tab Before", "\tfalse",
|
||||
self.make_success_test("Bool False Tab Before", "\\tfalse",
|
||||
"bool", False)
|
||||
|
||||
def generate_error_tests(self):
|
||||
"""Generate error test cases for booleans."""
|
||||
# Capitalized (case sensitive)
|
||||
self.make_error_test("Bool True Capitalized",
|
||||
"True",
|
||||
"Invalid boolean: 'True' is not a boolean literal (use lowercase 'true').")
|
||||
self.make_success_test("Bool True Capitalized", "True",
|
||||
"identifier", "True")
|
||||
|
||||
self.make_error_test("Bool False Capitalized",
|
||||
"False",
|
||||
"Invalid boolean: 'False' is not a boolean literal (use lowercase 'false').")
|
||||
self.make_success_test("Bool False Capitalized", "False",
|
||||
"identifier", "False")
|
||||
|
||||
# All caps
|
||||
self.make_error_test("Bool True All Caps",
|
||||
"TRUE",
|
||||
"Invalid boolean: 'TRUE' is not a boolean literal (use lowercase 'true').")
|
||||
self.make_success_test("Bool True All Caps", "TRUE",
|
||||
"identifier", "TRUE")
|
||||
|
||||
self.make_error_test("Bool False All Caps",
|
||||
"FALSE",
|
||||
"Invalid boolean: 'FALSE' is not a boolean literal (use lowercase 'false').")
|
||||
self.make_success_test("Bool False All Caps", "FALSE",
|
||||
"identifier", "FALSE")
|
||||
|
||||
# Mixed case
|
||||
self.make_error_test("Bool True Mixed Case",
|
||||
"tRuE",
|
||||
"Invalid boolean: 'tRuE' is not a boolean literal (use lowercase 'true').")
|
||||
self.make_success_test("Bool True Mixed Case", "tRuE",
|
||||
"identifier", "tRuE")
|
||||
|
||||
self.make_error_test("Bool False Mixed Case",
|
||||
"fAlSe",
|
||||
"Invalid boolean: 'fAlSe' is not a boolean literal (use lowercase 'false').")
|
||||
self.make_success_test("Bool False Mixed Case", "fAlSe",
|
||||
"identifier", "fAlSe")
|
||||
|
||||
# Numeric representations
|
||||
self.make_error_test("Bool Numeric 1",
|
||||
"1",
|
||||
"Not a boolean: numeric literal.")
|
||||
self.make_success_test("Bool Numeric 1", "1", "i64", 1)
|
||||
|
||||
self.make_error_test("Bool Numeric 0",
|
||||
"0",
|
||||
"Not a boolean: numeric literal.")
|
||||
self.make_success_test("Bool Numeric 0", "0", "i64", 0)
|
||||
|
||||
# String representations
|
||||
self.make_error_test("Bool String True",
|
||||
'"true"',
|
||||
"Not a boolean: string literal.")
|
||||
self.make_success_test("Bool String True", '"true"',
|
||||
"string", "true")
|
||||
|
||||
self.make_error_test("Bool String False",
|
||||
'"false"',
|
||||
"Not a boolean: string literal.")
|
||||
self.make_success_test("Bool String False", '"false"',
|
||||
"string", "false")
|
||||
|
||||
# Other languages
|
||||
self.make_error_test("Bool Yes",
|
||||
"yes",
|
||||
"Invalid boolean: 'yes' is not a boolean literal.")
|
||||
self.make_success_test("Bool Yes", "yes",
|
||||
"identifier", "yes")
|
||||
|
||||
self.make_error_test("Bool No",
|
||||
"no",
|
||||
"Invalid boolean: 'no' is not a boolean literal.")
|
||||
self.make_success_test("Bool No", "no",
|
||||
"identifier", "no")
|
||||
|
||||
# Typos
|
||||
self.make_error_test("Bool Typo Ture",
|
||||
"ture",
|
||||
"Invalid boolean: 'ture' is not a boolean literal.")
|
||||
self.make_success_test("Bool Typo Ture", "ture",
|
||||
"identifier", "ture")
|
||||
|
||||
self.make_error_test("Bool Typo Flase",
|
||||
"flase",
|
||||
"Invalid boolean: 'flase' is not a boolean literal.")
|
||||
self.make_success_test("Bool Typo Flase", "flase",
|
||||
"identifier", "flase")
|
||||
|
||||
def generate_multiple_bool_tests(self):
|
||||
"""Generate tests with multiple boolean values."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue