Worked on getting tests compiling

This commit is contained in:
Kyler Olsen 2025-11-16 20:34:38 -07:00
parent 690155b9a7
commit 4398b3a4bc
8 changed files with 2238 additions and 566 deletions

View File

@ -110,9 +110,10 @@ TestResult pass_test(LexerTest *test, LexerResult result);
Boolean test_eof_value(LexerTest *test, LexerResult result, size_t i, void *_); Boolean test_eof_value(LexerTest *test, LexerResult result, size_t i, void *_);
Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, TestIdentifierValue *value); Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, TestIdentifierValue *value);
Boolean test_integer_value(LexerTest *test, LexerResult result, size_t i, TestIntegerValue *value); Boolean test_integer_value(LexerTest *test, LexerResult result, size_t i, TestIntegerValue *value);
Boolean test_character_value(LexerTest *test, LexerResult result, size_t i, uint8_t *value);
Boolean test_float_value(LexerTest *test, LexerResult result, size_t i, float *value); Boolean test_float_value(LexerTest *test, LexerResult result, size_t i, float *value);
Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double *value); Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double *value);
Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr value); Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr *value);
Boolean test_boolean_value(LexerTest *test, LexerResult result, size_t i, Boolean *value); Boolean test_boolean_value(LexerTest *test, LexerResult result, size_t i, Boolean *value);
Boolean test_array_identifier_value(LexerTest *test, LexerResult result, size_t i, TestArrayIdentifierValue *values); Boolean test_array_identifier_value(LexerTest *test, LexerResult result, size_t i, TestArrayIdentifierValue *values);
Boolean test_array_integer_value(LexerTest *test, LexerResult result, size_t i, TestArrayIntegerValue *values); Boolean test_array_integer_value(LexerTest *test, LexerResult result, size_t i, TestArrayIntegerValue *values);

View File

@ -326,16 +326,16 @@ Boolean test_double_value(LexerTest *test, LexerResult result, size_t i, double
return FALSE; return FALSE;
} }
Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr value) { Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr *value) {
static const TokenType token_type = TOKEN_STRING; static const TokenType token_type = TOKEN_STRING;
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 (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 (sls_str_cmp(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;
} }
return FALSE; return FALSE;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,8 @@ class BaseTestGenerator(ABC):
test creation, operation building, and error handling. test creation, operation building, and error handling.
""" """
ENABLE_UNICODE = False
__generators: "ClassVar[List[Type[BaseTestGenerator]]]" = [] __generators: "ClassVar[List[Type[BaseTestGenerator]]]" = []
def __init_subclass__(cls): def __init_subclass__(cls):

View File

@ -5,8 +5,6 @@ from .base_tests import BaseTestGenerator
class CharTestGenerator(BaseTestGenerator): class CharTestGenerator(BaseTestGenerator):
"""Generate test cases for character literals.""" """Generate test cases for character literals."""
ENABLE_UNICODE = False
# Common escape sequences # Common escape sequences
ESCAPE_SEQUENCES = { ESCAPE_SEQUENCES = {
("Newline", '\\n', '\n',), # Newline ("Newline", '\\n', '\n',), # Newline
@ -192,16 +190,16 @@ class CharTestGenerator(BaseTestGenerator):
# Invalid escape sequence # Invalid escape sequence
self.make_error_test("Char Invalid Escape", self.make_error_test("Char Invalid Escape",
"'\\q'", "'\\\\q'",
"Invalid character literal: unknown escape sequence '\\q'.") "Invalid character literal: unknown escape sequence '\\\\q'.")
# Invalid hex escape (not 2 digits) # Invalid hex escape (not 2 digits)
self.make_error_test("Char Hex Escape Too Short", self.make_error_test("Char Hex Escape Too Short",
"'\\x4'", "'\\\\x4'",
"Invalid character literal: hexadecimal escape must have exactly 2 digits.") "Invalid character literal: hexadecimal escape must have exactly 2 digits.")
self.make_error_test("Char Hex Escape Too Long", self.make_error_test("Char Hex Escape Too Long",
"'\\x414'", "'\\\\x414'",
"Invalid character literal: hexadecimal escape must have exactly 2 digits.") "Invalid character literal: hexadecimal escape must have exactly 2 digits.")
# Invalid hex digits # Invalid hex digits

View File

@ -19,301 +19,301 @@ class StringTestGenerator(BaseTestGenerator):
def generate_basic_tests(self): def generate_basic_tests(self):
"""Generate basic string literal tests.""" """Generate basic string literal tests."""
# Empty string # Empty string
self.make_success_test("String Empty", '""', "String", "") self.make_success_test("String Empty", '""', "string", "")
# Simple strings # Simple strings
self.make_success_test("String Simple", '"hello"', "String", "hello") self.make_success_test("String Simple", '"hello"', "string", "hello")
self.make_success_test("String With Space", '"hello world"', "String", "hello world") self.make_success_test("String With Space", '"hello world"', "string", "hello world")
self.make_success_test("String Single Char", '"A"', "String", "A") self.make_success_test("String Single Char", '"A"', "string", "A")
# Multiple words # Multiple words
self.make_success_test("String Multiple Words", self.make_success_test("String Multiple Words",
'"The quick brown fox"', "String", "The quick brown fox") '"The quick brown fox"', "string", "The quick brown fox")
# Numbers in strings # Numbers in strings
self.make_success_test("String With Numbers", '"abc123"', "String", "abc123") self.make_success_test("String With Numbers", '"abc123"', "string", "abc123")
self.make_success_test("String Only Numbers", '"12345"', "String", "12345") self.make_success_test("String Only Numbers", '"12345"', "string", "12345")
# Mixed case # Mixed case
self.make_success_test("String Mixed Case", '"HeLLo WoRLd"', "String", "HeLLo WoRLd") self.make_success_test("String Mixed Case", '"HeLLo WoRLd"', "string", "HeLLo WoRLd")
# Special characters # Special characters
self.make_success_test("String With Punctuation", self.make_success_test("String With Punctuation",
'"Hello, World!"', "String", "Hello, World!") '"Hello, World!"', "string", "Hello, World!")
self.make_success_test("String With Symbols", self.make_success_test("String With Symbols",
'"@#$%^&*()"', "String", "@#$%^&*()") '"@#$%^&*()"', "string", "@#$%^&*()")
# Spaces # Spaces
self.make_success_test("String Multiple Spaces", self.make_success_test("String Multiple Spaces",
'"hello world"', "String", "hello world") '"hello world"', "string", "hello world")
self.make_success_test("String Leading Space", '" hello"', "String", " hello") self.make_success_test("String Leading Space", '" hello"', "string", " hello")
self.make_success_test("String Trailing Space", '"hello "', "String", "hello ") self.make_success_test("String Trailing Space", '"hello "', "string", "hello ")
self.make_success_test("String Only Spaces", '" "', "String", " ") self.make_success_test("String Only Spaces", '" "', "string", " ")
def generate_escape_sequence_tests(self): def generate_escape_sequence_tests(self):
"""Generate tests for escape sequences.""" """Generate tests for escape sequences."""
# Individual escape sequences # Individual escape sequences
self.make_success_test("String Newline", '"hello\\nworld"', self.make_success_test("String Newline", '"hello\\nworld"',
"String", "hello\nworld") "string", "hello\\nworld")
self.make_success_test("String Tab", '"hello\\tworld"', self.make_success_test("String Tab", '"hello\\tworld"',
"String", "hello\tworld") "string", "hello\\tworld")
self.make_success_test("String Carriage Return", '"hello\\rworld"', self.make_success_test("String Carriage Return", '"hello\\rworld"',
"String", "hello\rworld") "string", "hello\\rworld")
self.make_success_test("String Backslash", '"hello\\\\world"', self.make_success_test("String Backslash", '"hello\\\\world"',
"String", "hello\\world") "string", "hello\\\\world")
self.make_success_test("String Double Quote", '"say \\"hello\\""', self.make_success_test("String Double Quote", '"say \\\\"hello\\\\""',
"String", 'say "hello"') "string", 'say \\"hello\\"')
self.make_success_test("String Single Quote", '"it\\\'s"', self.make_success_test("String Single Quote", '"it\\\'s"',
"String", "it's") "string", "it's")
self.make_success_test("String Null Char", '"hello\\0world"', self.make_success_test("String Null Char", '"hello\\0world"',
"String", "hello\0world") "string", "hello\\0world")
# Multiple escape sequences # Multiple escape sequences
self.make_success_test("String Multiple Escapes", self.make_success_test("String Multiple Escapes",
'"line1\\nline2\\nline3"', '"line1\\nline2\\nline3"',
"String", "line1\nline2\nline3") "string", "line1\\nline2\\nline3")
self.make_success_test("String Mixed Escapes", self.make_success_test("String Mixed Escapes",
'"tab\\there\\nnewline\\\\backslash"', '"tab\\there\\nnewline\\\\backslash"',
"String", "tab\there\nnewline\\backslash") "string", "tab\\there\\nnewline\\\\backslash")
# Escape at start/end # Escape at start/end
self.make_success_test("String Escape At Start", '"\\nhello"', self.make_success_test("String Escape At Start", '"\\nhello"',
"String", "\nhello") "string", "\\nhello")
self.make_success_test("String Escape At End", '"hello\\n"', self.make_success_test("String Escape At End", '"hello\\n"',
"String", "hello\n") "string", "hello\\n")
# Consecutive escapes # Consecutive escapes
self.make_success_test("String Consecutive Escapes", '"\\n\\n\\n"', self.make_success_test("String Consecutive Escapes", '"\\n\\n\\n"',
"String", "\n\n\n") "string", "\\n\\n\\n")
self.make_success_test("String All Escapes", '"\\n\\r\\t\\\\\\"\\\'\\0"', self.make_success_test("String All Escapes", '"\\n\\r\\t\\\\"\\\'\\0"',
"String", "\n\r\t\\\"\'\0") "string", "\\n\\r\\t\\\\\\\"\\'\\0")
def generate_hexadecimal_escape_tests(self): def generate_hexadecimal_escape_tests(self):
"""Generate tests for hexadecimal escape sequences.""" """Generate tests for hexadecimal escape sequences."""
# Basic hex escapes # Basic hex escapes
self.make_success_test("String Hex Letter A", '"\\x41"', "String", "A") self.make_success_test("String Hex Letter A", '"\\x41"', "string", "A")
self.make_success_test("String Hex Letter a", '"\\x61"', "String", "a") self.make_success_test("String Hex Letter a", '"\\x61"', "string", "a")
self.make_success_test("String Hex Space", '"\\x20"', "String", " ") self.make_success_test("String Hex Space", '"\\x20"', "string", " ")
self.make_success_test("String Hex Tab", '"\\x09"', "String", "\t") self.make_success_test("String Hex Tab", '"\\x09"', "string", "\\t")
self.make_success_test("String Hex Newline", '"\\x0A"', "String", "\n") self.make_success_test("String Hex Newline", '"\\x0A"', "string", "\\n")
# Multiple hex escapes # Multiple hex escapes
self.make_success_test("String Multiple Hex", '"\\x48\\x65\\x6C\\x6C\\x6F"', self.make_success_test("String Multiple Hex", '"\\x48\\x65\\x6C\\x6C\\x6F"',
"String", "Hello") "string", "Hello")
# Hex with regular text # Hex with regular text
self.make_success_test("String Hex Mixed", '"Hello\\x20World"', self.make_success_test("String Hex Mixed", '"Hello\\x20World"',
"String", "Hello World") "string", "Hello World")
# Extended ASCII # Extended ASCII
self.make_success_test("String Hex Extended ASCII", '"\\xA9\\xAE"', self.make_success_test("String Hex Extended ASCII", '"\\xA9\\xAE"',
"String", "\xA9\xAE") "string", "\xA9\xAE")
# Case variations # Case variations
self.make_success_test("String Hex Uppercase", '"\\xFF"', "String", "\xFF") self.make_success_test("String Hex Uppercase", '"\\xFF"', "string", "\\xFF")
self.make_success_test("String Hex Lowercase", '"\\xff"', "String", "\xff") self.make_success_test("String Hex Lowercase", '"\\xff"', "string", "\\xff")
self.make_success_test("String Hex Mixed Case", '"\\xAb"', "String", "\xAb") self.make_success_test("String Hex Mixed Case", '"\\xAb"', "string", "\\xAb")
# All hex values # All hex values
self.make_success_test("String Hex Zero", '"\\x00"', "String", "\x00") self.make_success_test("String Hex Zero", '"\\x00"', "string", "\\0")
self.make_success_test("String Hex Max", '"\\xFF"', "String", "\xFF") self.make_success_test("String Hex Max", '"\\xFF"', "string", "\\xFF")
def generate_unicode_escape_tests(self): def generate_unicode_escape_tests(self):
"""Generate tests for Unicode escape sequences.""" """Generate tests for Unicode escape sequences."""
# Basic Unicode escapes # Basic Unicode escapes
self.make_success_test("String Unicode Letter A", '"\\u{41}"', "String", "A") self.make_success_test("String Unicode Letter A", '"\\u{41}"', "string", "A")
self.make_success_test("String Unicode Space", '"\\u{20}"', "String", " ") self.make_success_test("String Unicode Space", '"\\u{20}"', "string", " ")
# Emoji # Emoji
self.make_success_test("String Unicode Smiley", '"\\u{1F600}"', self.make_success_test("String Unicode Smiley", '"\\u{1F600}"',
"String", "😀") "string", "😀")
self.make_success_test("String Unicode Heart", '"\\u{2764}"', self.make_success_test("String Unicode Heart", '"\\u{2764}"',
"String", "") "string", "")
self.make_success_test("String Unicode Star", '"\\u{2B50}"', self.make_success_test("String Unicode Star", '"\\u{2B50}"',
"String", "") "string", "")
# Multiple emoji # Multiple emoji
self.make_success_test("String Multiple Emoji", self.make_success_test("String Multiple Emoji",
'"\\u{1F600}\\u{2764}\\u{2B50}"', '"\\u{1F600}\\u{2764}\\u{2B50}"',
"String", "😀❤⭐") "string", "😀❤⭐")
# Greek letters # Greek letters
self.make_success_test("String Unicode Greek Alpha", '"\\u{03B1}"', self.make_success_test("String Unicode Greek Alpha", '"\\u{03B1}"',
"String", "α") "string", "α")
self.make_success_test("String Unicode Greek Beta", '"\\u{03B2}"', self.make_success_test("String Unicode Greek Beta", '"\\u{03B2}"',
"String", "β") "string", "β")
# Chinese characters # Chinese characters
self.make_success_test("String Unicode Chinese", '"\\u{4E2D}\\u{6587}"', self.make_success_test("String Unicode Chinese", '"\\u{4E2D}\\u{6587}"',
"String", "中文") "string", "中文")
# Arabic # Arabic
self.make_success_test("String Unicode Arabic", '"\\u{0639}\\u{0631}\\u{0628}"', self.make_success_test("String Unicode Arabic", '"\\u{0639}\\u{0631}\\u{0628}"',
"String", "عرب") "string", "عرب")
# Cyrillic # Cyrillic
self.make_success_test("String Unicode Cyrillic", '"\\u{0420}\\u{0443}\\u{0441}"', self.make_success_test("String Unicode Cyrillic", '"\\u{0420}\\u{0443}\\u{0441}"',
"String", "Рус") "string", "Рус")
# Mathematical symbols # Mathematical symbols
self.make_success_test("String Unicode Math", '"\\u{221E}\\u{2211}\\u{222B}"', self.make_success_test("String Unicode Math", '"\\u{221E}\\u{2211}\\u{222B}"',
"String", "∞∑∫") "string", "∞∑∫")
# Mixed with regular text # Mixed with regular text
self.make_success_test("String Unicode Mixed", '"Hello \\u{1F600} World"', self.make_success_test("String Unicode Mixed", '"Hello \\u{1F600} World"',
"String", "Hello 😀 World") "string", "Hello 😀 World")
# Case variations in hex digits # Case variations in hex digits
self.make_success_test("String Unicode Hex Uppercase", '"\\u{1F600}"', self.make_success_test("String Unicode Hex Uppercase", '"\\u{1F600}"',
"String", "😀") "string", "😀")
self.make_success_test("String Unicode Hex Lowercase", '"\\u{1f600}"', self.make_success_test("String Unicode Hex Lowercase", '"\\u{1f600}"',
"String", "😀") "string", "😀")
self.make_success_test("String Unicode Hex Mixed", '"\\u{1F60a}"', self.make_success_test("String Unicode Hex Mixed", '"\\u{1F60a}"',
"String", "😊") "string", "😊")
# Variable length code points # Variable length code points
self.make_success_test("String Unicode 2 Digits", '"\\u{41}"', "String", "A") self.make_success_test("String Unicode 2 Digits", '"\\u{41}"', "string", "A")
self.make_success_test("String Unicode 4 Digits", '"\\u{03B1}"', "String", "α") self.make_success_test("String Unicode 4 Digits", '"\\u{03B1}"', "string", "α")
self.make_success_test("String Unicode 5 Digits", '"\\u{1F600}"', "String", "😀") self.make_success_test("String Unicode 5 Digits", '"\\u{1F600}"', "string", "😀")
self.make_success_test("String Unicode 6 Digits", '"\\u{10FFFF}"', self.make_success_test("String Unicode 6 Digits", '"\\u{10FFFF}"',
"String", "\U0010FFFF") "string", "\U0010FFFF")
def generate_direct_unicode_tests(self): def generate_direct_unicode_tests(self):
"""Generate tests for direct Unicode characters in strings.""" """Generate tests for direct Unicode characters in strings."""
# Direct emoji # Direct emoji
self.make_success_test("String Direct Emoji", '"Hello 😀 World"', self.make_success_test("String Direct Emoji", '"Hello 😀 World"',
"String", "Hello 😀 World") "string", "Hello 😀 World")
self.make_success_test("String Multiple Direct Emoji", '"😀❤⭐👍"', self.make_success_test("String Multiple Direct Emoji", '"😀❤⭐👍"',
"String", "😀❤⭐👍") "string", "😀❤⭐👍")
# Direct Greek # Direct Greek
self.make_success_test("String Direct Greek", '"αβγδ"', "String", "αβγδ") self.make_success_test("String Direct Greek", '"αβγδ"', "string", "αβγδ")
# Direct Chinese # Direct Chinese
self.make_success_test("String Direct Chinese", '"你好世界"', self.make_success_test("String Direct Chinese", '"你好世界"',
"String", "你好世界") "string", "你好世界")
# Direct Arabic # Direct Arabic
self.make_success_test("String Direct Arabic", '"مرحبا"', "String", "مرحبا") self.make_success_test("String Direct Arabic", '"مرحبا"', "string", "مرحبا")
# Direct Cyrillic # Direct Cyrillic
self.make_success_test("String Direct Cyrillic", '"Привет"', self.make_success_test("String Direct Cyrillic", '"Привет"',
"String", "Привет") "string", "Привет")
# Direct mathematical # Direct mathematical
self.make_success_test("String Direct Math", '"∞∑∫√π"', "String", "∞∑∫√π") self.make_success_test("String Direct Math", '"∞∑∫√π"', "string", "∞∑∫√π")
# Mixed scripts # Mixed scripts
self.make_success_test("String Mixed Scripts", '"Hello 世界 Привет"', self.make_success_test("String Mixed Scripts", '"Hello 世界 Привет"',
"String", "Hello 世界 Привет") "string", "Hello 世界 Привет")
def generate_multiline_tests(self): def generate_multiline_tests(self):
"""Generate tests for strings with embedded newlines.""" """Generate tests for strings with embedded newlines."""
# Strings with escape newlines # Strings with escape newlines
self.make_success_test("String With Escaped Newlines", self.make_success_test("String With Escaped Newlines",
'"line1\\nline2\\nline3"', '"line1\\nline2\\nline3"',
"String", "line1\nline2\nline3") "string", "line1\\nline2\\nline3")
# Paragraph-like text # Paragraph-like text
self.make_success_test("String Paragraph", self.make_success_test("String Paragraph",
'"First line.\\nSecond line.\\nThird line."', '"First line.\\nSecond line.\\nThird line."',
"String", "First line.\nSecond line.\nThird line.") "string", "First line.\\nSecond line.\\nThird line.")
# Mixed line endings # Mixed line endings
self.make_success_test("String Mixed Line Endings", self.make_success_test("String Mixed Line Endings",
'"Windows\\r\\nUnix\\nMac\\r"', '"Windows\\r\\nUnix\\nMac\\r"',
"String", "Windows\r\nUnix\nMac\r") "string", "Windows\\r\\nUnix\\nMac\\r")
def generate_whitespace_tests(self): def generate_whitespace_tests(self):
"""Generate tests with various whitespace.""" """Generate tests with various whitespace."""
# Leading/trailing whitespace outside quotes # Leading/trailing whitespace outside quotes
self.make_success_test("String Leading Whitespace Outside", self.make_success_test("String Leading Whitespace Outside",
' "hello"', "String", "hello") ' "hello"', "string", "hello")
self.make_success_test("String Trailing Whitespace Outside", self.make_success_test("String Trailing Whitespace Outside",
'"hello" ', "String", "hello") '"hello" ', "string", "hello")
self.make_success_test("String Both Whitespace Outside", self.make_success_test("String Both Whitespace Outside",
' "hello" ', "String", "hello") ' "hello" ', "string", "hello")
# Tabs outside quotes # Tabs outside quotes
self.make_success_test("String Tab Before", '\t"hello"', "String", "hello") self.make_success_test("String Tab Before", '\t"hello"', "string", "hello")
# Mixed whitespace # Mixed whitespace
self.make_success_test("String Tabs And Newlines Inside", self.make_success_test("String Tabs And Newlines Inside",
'"hello\\t\\tworld\\n\\ntest"', '"hello\\t\\tworld\\n\\ntest"',
"String", "hello\t\tworld\n\ntest") "string", "hello\\t\\tworld\\n\\ntest")
# Only whitespace inside # Only whitespace inside
self.make_success_test("String Only Tabs", '"\\t\\t\\t"', "String", "\t\t\t") self.make_success_test("String Only Tabs", '"\\t\\t\\t"', "string", "\\t\\t\\t")
self.make_success_test("String Only Newlines", '"\\n\\n\\n"', "String", "\n\n\n") self.make_success_test("String Only Newlines", '"\\n\\n\\n"', "string", "\\n\\n\\n")
self.make_success_test("String Mixed Whitespace", '" \\t\\n\\r "', self.make_success_test("String Mixed Whitespace", '" \\t\\n\\r "',
"String", " \t\n\r ") "string", " \\t\\n\\r ")
def generate_long_string_tests(self): def generate_long_string_tests(self):
"""Generate tests for longer strings.""" """Generate tests for longer strings."""
# Sentence # Sentence
self.make_success_test("String Sentence", self.make_success_test("String Sentence",
'"The quick brown fox jumps over the lazy dog."', '"The quick brown fox jumps over the lazy dog."',
"String", "The quick brown fox jumps over the lazy dog.") "string", "The quick brown fox jumps over the lazy dog.")
# Multiple sentences # Multiple sentences
self.make_success_test("String Multiple Sentences", self.make_success_test("String Multiple Sentences",
'"First sentence. Second sentence. Third sentence."', '"First sentence. Second sentence. Third sentence."',
"String", "First sentence. Second sentence. Third sentence.") "string", "First sentence. Second sentence. Third sentence.")
# Long string with escapes # Long string with escapes
long_str = "This is a long string.\\nIt has multiple lines.\\nAnd some tabs\\there.\\nPlus quotes \\\"like this\\\"." long_str = '"This is a long string.\\nIt has multiple lines.\\nAnd some tabs\\there.\\nPlus quotes "like this"."'
expected = "This is a long string.\nIt has multiple lines.\nAnd some tabs\there.\nPlus quotes \"like this\"." expected = "This is a long string.\\nIt has multiple lines.\\nAnd some tabs\\there.\\nPlus quotes \\\"like this\\\"."
self.make_success_test("String Long With Escapes", f'"{long_str}"', self.make_success_test("String Long With Escapes", long_str,
"String", expected) "string", expected)
# Repetitive string # Repetitive string
self.make_success_test("String Repetitive", '"aaaaaaaaaa"', self.make_success_test("String Repetitive", '"aaaaaaaaaa"',
"String", "aaaaaaaaaa") "string", "aaaaaaaaaa")
# All ASCII printable characters # All ASCII printable characters
printable = "".join(chr(i) for i in range(32, 127) if chr(i) not in ['"', '\\']) printable = "".join(chr(i) for i in range(32, 127) if chr(i) not in ['"', '\\'])
self.make_success_test("String ASCII Printable", self.make_success_test("String ASCII Printable",
f'"{printable}"', "String", printable) f'"{printable}"', "string", printable)
def generate_special_content_tests(self): def generate_special_content_tests(self):
"""Generate tests for strings with special content.""" """Generate tests for strings with special content."""
# Code-like strings # Code-like strings
self.make_success_test("String Code Like", self.make_success_test("String Code Like",
'"int main() { return 0; }"', '"int main() { return 0; }"',
"String", "int main() { return 0; }") "string", "int main() { return 0; }")
# JSON-like strings # JSON-like strings
self.make_success_test("String JSON Like", self.make_success_test("String JSON Like",
'"{{\\"key\\": \\"value\\"}}"', '"{{\\\\"key\\\\": \\\\"value\\\\"}}"',
"String", '{"key": "value"}') "string", '{\\"key\\": \\"value\\"}')
# URL # URL
self.make_success_test("String URL", self.make_success_test("String URL",
'"https://example.com/path?query=value"', '"https://example.com/path?query=value"',
"String", "https://example.com/path?query=value") "string", "https://example.com/path?query=value")
# Email # Email
self.make_success_test("String Email", self.make_success_test("String Email",
'"user@example.com"', "String", "user@example.com") '"user@example.com"', "string", "user@example.com")
# File path (Unix) # File path (Unix)
self.make_success_test("String Unix Path", self.make_success_test("String Unix Path",
'"/home/user/file.txt"', '"/home/user/file.txt"',
"String", "/home/user/file.txt") "string", "/home/user/file.txt")
# File path (Windows) # File path (Windows)
self.make_success_test("String Windows Path", self.make_success_test("String Windows Path",
'"C:\\\\Users\\\\file.txt"', '"C:\\\\Users\\\\file.txt"',
"String", "C:\\Users\\file.txt") "string", "C:\\\\Users\\\\file.txt")
# SQL-like # SQL-like
self.make_success_test("String SQL Like", self.make_success_test("String SQL Like",
'"SELECT * FROM users WHERE id = 1"', '"SELECT * FROM users WHERE id = 1"',
"String", "SELECT * FROM users WHERE id = 1") "string", "SELECT * FROM users WHERE id = 1")
# Regular expression # Regular expression
self.make_success_test("String Regex Like", self.make_success_test("String Regex Like",
'"[a-zA-Z0-9]+"', "String", "[a-zA-Z0-9]+") '"[a-zA-Z0-9]+"', "string", "[a-zA-Z0-9]+")
def generate_error_tests(self): def generate_error_tests(self):
"""Generate error test cases.""" """Generate error test cases."""
@ -324,13 +324,13 @@ class StringTestGenerator(BaseTestGenerator):
# Unescaped newline # Unescaped newline
self.make_error_test("String Unescaped Newline", self.make_error_test("String Unescaped Newline",
'"hello\nworld"', '"hello\\nworld"',
"Invalid string literal: unescaped newline in string literal.") "Invalid string literal: unescaped newline in string literal.")
# Invalid escape sequence # Invalid escape sequence
self.make_error_test("String Invalid Escape", self.make_error_test("String Invalid Escape",
'"hello\\qworld"', '"hello\\\\qworld"',
"Invalid string literal: unknown escape sequence '\\q'.") "Invalid string literal: unknown escape sequence '\\\\q'.")
# Hex escape too short # Hex escape too short
self.make_error_test("String Hex Too Short", self.make_error_test("String Hex Too Short",
@ -339,48 +339,49 @@ class StringTestGenerator(BaseTestGenerator):
# Hex escape too long # Hex escape too long
self.make_error_test("String Hex Too Long", self.make_error_test("String Hex Too Long",
'"\\x414"', '"\\\\x414"',
"Invalid string literal: hexadecimal escape must have exactly 2 digits.") "Invalid string literal: hexadecimal escape must have exactly 2 digits.")
# Invalid hex digits # Invalid hex digits
self.make_error_test("String Hex Invalid Digit", self.make_error_test("String Hex Invalid Digit",
'"\\xGG"', '"\\\\xGG"',
"Invalid string literal: invalid hexadecimal digit 'G'.") "Invalid string literal: invalid hexadecimal digit 'G'.")
# Unicode no braces if self.ENABLE_UNICODE:
self.make_error_test("String Unicode No Braces", # Unicode no braces
'"\\u1F600"', self.make_error_test("String Unicode No Braces",
"Invalid string literal: Unicode escape must use braces \\u{...}.") '"\\u1F600"',
"Invalid string literal: Unicode escape must use braces \\u{...}.")
# Unicode empty
self.make_error_test("String Unicode Empty", # Unicode empty
'"\\u{}"', self.make_error_test("String Unicode Empty",
"Invalid string literal: empty Unicode escape sequence.") '"\\u{}"',
"Invalid string literal: empty Unicode escape sequence.")
# Unicode too long
self.make_error_test("String Unicode Too Long", # Unicode too long
'"\\u{1234567}"', self.make_error_test("String Unicode Too Long",
"Invalid string literal: Unicode escape sequence too long (max 6 hex digits).") '"\\u{1234567}"',
"Invalid string literal: Unicode escape sequence too long (max 6 hex digits).")
# Unicode invalid code point (surrogate)
self.make_error_test("String Unicode Surrogate", # Unicode invalid code point (surrogate)
'"\\u{D800}"', self.make_error_test("String Unicode Surrogate",
"Invalid string literal: invalid Unicode code point (surrogate range).") '"\\u{D800}"',
"Invalid string literal: invalid Unicode code point (surrogate range).")
# Unicode out of range
self.make_error_test("String Unicode Out Of Range", # Unicode out of range
'"\\u{110000}"', self.make_error_test("String Unicode Out Of Range",
"Invalid string literal: Unicode code point out of range (max 0x10FFFF).") '"\\u{110000}"',
"Invalid string literal: Unicode code point out of range (max 0x10FFFF).")
# Unicode invalid hex
self.make_error_test("String Unicode Invalid Hex", # Unicode invalid hex
'"\\u{GGGG}"', self.make_error_test("String Unicode Invalid Hex",
"Invalid string literal: invalid hexadecimal digit 'G' in Unicode escape.") '"\\u{GGGG}"',
"Invalid string literal: invalid hexadecimal digit 'G' in Unicode escape.")
# Unclosed Unicode escape
self.make_error_test("String Unicode Unclosed", # Unclosed Unicode escape
'"\\u{1F600"', self.make_error_test("String Unicode Unclosed",
"Invalid string literal: unclosed Unicode escape sequence.") '"\\u{1F600"',
"Invalid string literal: unclosed Unicode escape sequence.")
# Single quotes instead of double # Single quotes instead of double
self.make_error_test("String Single Quotes", self.make_error_test("String Single Quotes",
@ -389,48 +390,49 @@ class StringTestGenerator(BaseTestGenerator):
# Backslash at end # Backslash at end
self.make_error_test("String Backslash At End", self.make_error_test("String Backslash At End",
'"hello\\"', '"hello\\\\"',
"Invalid string literal: incomplete escape sequence at end.") "Invalid string literal: incomplete escape sequence at end.")
def generate_edge_case_tests(self): def generate_edge_case_tests(self):
"""Generate edge case tests.""" """Generate edge case tests."""
# String with only escape sequences # String with only escape sequences
self.make_success_test("String Only Escapes", self.make_success_test("String Only Escapes",
'"\\n\\t\\r"', "String", "\n\t\r") '"\\n\\t\\r"', "string", "\\n\\t\\r")
# String with null characters # String with null characters
self.make_success_test("String With Nulls", self.make_success_test("String With Nulls",
'"a\\0b\\0c"', "String", "a\0b\0c") '"a\\0b\\0c"', "string", "a\\0b\\0c")
# Very long escape sequence # Very long escape sequence
self.make_success_test("String Many Escapes", self.make_success_test("String Many Escapes",
'"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"', '"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"',
"String", "\n\n\n\n\n\n\n\n\n\n") "string", "\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n")
# Mixed escape types if self.ENABLE_UNICODE:
self.make_success_test("String All Escape Types", # Mixed escape types
'"\\n\\x41\\u{42}test"', self.make_success_test("String All Escape Types",
"String", "\nABtest") '"\\n\\x41\\u{42}test"',
"string", "\nABtest")
# Zero-width characters
self.make_success_test("String Zero Width", # Zero-width characters
'"hello\\u{200B}world"', self.make_success_test("String Zero Width",
"String", "hello\u200Bworld") '"hello\\u{200B}world"',
"string", "hello\u200Bworld")
# Combining characters
self.make_success_test("String Combining", # Combining characters
'"e\\u{0301}"', # é as e + combining acute self.make_success_test("String Combining",
"String", "e\u0301") '"e\\u{0301}"', # é as e + combining acute
"string", "e\u0301")
# Right-to-left
self.make_success_test("String RTL Mark", # Right-to-left
'"\\u{200F}hello"', self.make_success_test("String RTL Mark",
"String", "\u200Fhello") '"\\u{200F}hello"',
"string", "\u200Fhello")
# Byte order mark
self.make_success_test("String BOM", # Byte order mark
'"\\u{FEFF}hello"', self.make_success_test("String BOM",
"String", "\uFEFFhello") '"\\u{FEFF}hello"',
"string", "\uFEFFhello")
def generate_all_tests(self) -> List[Dict[str, Any]]: def generate_all_tests(self) -> List[Dict[str, Any]]:
"""Generate all string literal test cases.""" """Generate all string literal test cases."""
@ -443,11 +445,12 @@ class StringTestGenerator(BaseTestGenerator):
# Hexadecimal escapes # Hexadecimal escapes
self.generate_hexadecimal_escape_tests() self.generate_hexadecimal_escape_tests()
# Unicode escapes if self.ENABLE_UNICODE:
self.generate_unicode_escape_tests() # Unicode escapes
self.generate_unicode_escape_tests()
# Direct Unicode
self.generate_direct_unicode_tests() # Direct Unicode
self.generate_direct_unicode_tests()
# Multiline strings # Multiline strings
self.generate_multiline_tests() self.generate_multiline_tests()

View File

@ -74,6 +74,8 @@ def _token_to_c_call(token: dict, idx_var="i") -> str:
return f'test_float_value(&test, result, {idx_var}++, &(float){{{value}}})' return f'test_float_value(&test, result, {idx_var}++, &(float){{{value}}})'
elif ttype == "char": elif ttype == "char":
return f'test_character_value(&test, result, {idx_var}++, &(uint8_t){{{ord(value)}}})' # type: ignore return f'test_character_value(&test, result, {idx_var}++, &(uint8_t){{{ord(value)}}})' # type: ignore
elif ttype == "string":
return f'test_string_value(&test, result, {idx_var}++, &SLS_STR("{value}"))' # type: ignore
elif ttype == "identifier": elif ttype == "identifier":
return f'test_identifier_value(&test, result, {idx_var}++, &(TestIdentifierValue){{FALSE, {len(value)}, "{value}"}})' # type: ignore return f'test_identifier_value(&test, result, {idx_var}++, &(TestIdentifierValue){{FALSE, {len(value)}, "{value}"}})' # type: ignore
elif ttype == "identifier_literal": elif ttype == "identifier_literal":
@ -89,12 +91,13 @@ def token_to_c_call(token: dict, idx_var="i") -> str:
def generate_c_test(test: dict) -> str: def generate_c_test(test: dict) -> str:
"""Convert a single YAML test entry to a C test function.""" """Convert a single YAML test entry to a C test function."""
name = sanitize_name(test["name"]) name = test["name"]
c_name = sanitize_name(name)
code = c_string_literal(test["code"]) code = c_string_literal(test["code"])
tokens = test.get("tokens", []) tokens = test.get("tokens", [])
# Function header # Function header
c_code = [f"static TestResult {name}() {{", c_code = [f"static TestResult {c_name}() {{",
f' LexerTest test = start_up_test(SLS_STR("{name}"), SLS_STR("{code}"));', f' LexerTest test = start_up_test(SLS_STR("{name}"), SLS_STR("{code}"));',
" LexerResult result = lexical_analysis(&test.lexer_info);", " LexerResult result = lexical_analysis(&test.lexer_info);",
" if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error);", " if (result.type == SLS_ERROR) return error_fail_test(&test, result, result.error);",