diff --git a/SLS_Rust/sls/src/lib.rs b/SLS_Rust/sls/src/lib.rs new file mode 100644 index 0000000..134d811 --- /dev/null +++ b/SLS_Rust/sls/src/lib.rs @@ -0,0 +1,13 @@ +pub mod types; +pub mod errors; +pub mod file; +pub mod lexer; +pub mod interpreter; +pub mod repl; +pub mod meta; +pub mod builtin; + +// Re-export commonly used items for tests and external users +pub use crate::lexer::{Lexer, Token, TokenType}; +pub use crate::types::Value; +pub use crate::interpreter::Interpreter; diff --git a/SLS_Rust/sls/src/main.rs b/SLS_Rust/sls/src/main.rs index 2f58513..8f07065 100644 --- a/SLS_Rust/sls/src/main.rs +++ b/SLS_Rust/sls/src/main.rs @@ -1,13 +1,6 @@ -mod types; -mod errors; -mod file; -mod lexer; -mod interpreter; -mod repl; -mod meta; -mod builtin; - -use crate::interpreter::Interpreter; +use sls::interpreter::Interpreter; +use sls::meta; +use sls::repl; fn main() { println!("Starting sls (Rust) - {} v{}", meta::NAME, meta::VERSION); diff --git a/SLS_Rust/sls/tests/lexer_tests_generated.rs b/SLS_Rust/sls/tests/lexer_tests_generated.rs new file mode 100644 index 0000000..957d977 --- /dev/null +++ b/SLS_Rust/sls/tests/lexer_tests_generated.rs @@ -0,0 +1,6129 @@ +// Generated tests - do not edit by hand +// Use: run `python3 SLS_Tests/yaml_to_rust_tests.py SLS_Tests/cases.yaml tests/lexer_tests_generated.rs` + +use sls; // crate under test + +const INT64_MIN: i128 = i64::MIN as i128; +const UINT64_MAX: i128 = u64::MAX as i128; + +#[test] +fn test_Empty_Statement() { + let src = ""; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert!(got.is_empty()); +} + +#[test] +fn test_Integer_Default_Decimal_0() { + let src = "0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_Default_Decimal_1() { + let src = "-1"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -1); +} + +#[test] +fn test_Integer_Default_Decimal_42() { + let src = "42"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Default_Decimal_Leading_Zeros() { + let src = "00042"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Default_Hex_0xFF() { + let src = "0xFF"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_Default_Hex_0xdeadbeef() { + let src = "0xdeadbeef"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 3735928559); +} + +#[test] +fn test_Integer_Default_Hex_Max() { + let src = "0x7FFFFFFFFFFFFFFF"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 9223372036854775807); +} + +#[test] +fn test_Integer_Default_Binary_0b1010() { + let src = "0b1010"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 10); +} + +#[test] +fn test_Integer_Default_Binary_All_Ones() { + let src = "0b1111111111111111"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 65535); +} + +#[test] +fn test_Integer_Default_Octal_0o755() { + let src = "0o755"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 493); +} + +#[test] +fn test_Integer_Default_Octal_Max_Three_Digits() { + let src = "0o777"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 511); +} + +#[test] +fn test_Integer_Default_Decimal_Max_i64() { + let src = "9223372036854775807"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 9223372036854775807); +} + +#[test] +fn test_Integer_Default_Decimal_Min_i64() { + let src = "-9223372036854775808"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, INT64_MIN); +} + +#[test] +fn test_Integer_Default_Decimal_with_Underscore() { + let src = "1_000_000"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_Default_Underscore_End() { + let src = "42_"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Default_Underscore_Double() { + let src = "4__2"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Default_Whitespace() { + let src = " 42 "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Default_Hex_Zero() { + let src = "0x0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_Default_Binary_Zero() { + let src = "0b0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_Default_Octal_Zero() { + let src = "0o0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_Default_Decimal_with_Commas_Invalid() { + let src = "1,000,000"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_Default_Invalid_Characters() { + let src = "12a3"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_Default_Invalid_Prefix() { + let src = "0b2"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i8_Decimal_Positive() { + let src = "42:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_i8_Zero() { + let src = "0:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_i8_Decimal_Negative() { + let src = "-100:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -100); +} + +#[test] +fn test_Integer_i8_Hex() { + let src = "0x7F:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 127); +} + +#[test] +fn test_Integer_i8_Binary() { + let src = "0b1111:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_i8_Octal() { + let src = "0o77:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_i8_Max_Value() { + let src = "127:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 127); +} + +#[test] +fn test_Integer_i8_Min_Value() { + let src = "-128:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -128); +} + +#[test] +fn test_Integer_i8_Overflow() { + let src = "128:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i8_Underflow() { + let src = "-129:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i16_Decimal_Positive() { + let src = "42:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_i16_Zero() { + let src = "0:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_i16_Decimal_Negative() { + let src = "-100:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -100); +} + +#[test] +fn test_Integer_i16_Hex() { + let src = "0xFF:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_i16_Binary() { + let src = "0b1111:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_i16_Octal() { + let src = "0o77:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_i16_Max_Value() { + let src = "32767:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 32767); +} + +#[test] +fn test_Integer_i16_Min_Value() { + let src = "-32768:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -32768); +} + +#[test] +fn test_Integer_i16_Overflow() { + let src = "32768:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i16_Underflow() { + let src = "-32769:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i32_Decimal_Positive() { + let src = "42:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_i32_Zero() { + let src = "0:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_i32_Decimal_Negative() { + let src = "-100:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -100); +} + +#[test] +fn test_Integer_i32_Hex() { + let src = "0xFF:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_i32_Binary() { + let src = "0b1111:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_i32_Octal() { + let src = "0o77:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_i32_Max_Value() { + let src = "2147483647:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 2147483647); +} + +#[test] +fn test_Integer_i32_Min_Value() { + let src = "-2147483648:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -2147483648); +} + +#[test] +fn test_Integer_i32_Overflow() { + let src = "2147483648:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i32_Underflow() { + let src = "-2147483649:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i32_With_Underscores() { + let src = "1_000_000:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_i64_Decimal_Positive() { + let src = "42:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_i64_Zero() { + let src = "0:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_i64_Decimal_Negative() { + let src = "-100:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -100); +} + +#[test] +fn test_Integer_i64_Hex() { + let src = "0xFF:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_i64_Binary() { + let src = "0b1111:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_i64_Octal() { + let src = "0o77:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_i64_Max_Value() { + let src = "9223372036854775807:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 9223372036854775807); +} + +#[test] +fn test_Integer_i64_Min_Value() { + let src = "-9223372036854775808:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, INT64_MIN); +} + +#[test] +fn test_Integer_i64_Overflow() { + let src = "9223372036854775808:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i64_Underflow() { + let src = "-9223372036854775809:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_i64_With_Underscores() { + let src = "1_000_000:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_u8_Decimal_Positive() { + let src = "42:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_u8_Zero() { + let src = "0:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u8_Hex() { + let src = "0xFF:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u8_Binary() { + let src = "0b1111:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_u8_Octal() { + let src = "0o77:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_u8_Max_Value() { + let src = "255:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u8_Min_Value() { + let src = "0:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u8_Overflow() { + let src = "256:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u8_Underflow() { + let src = "-1:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u16_Decimal_Positive() { + let src = "42:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_u16_Zero() { + let src = "0:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u16_Hex() { + let src = "0xFF:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u16_Binary() { + let src = "0b1111:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_u16_Octal() { + let src = "0o77:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_u16_Max_Value() { + let src = "65535:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 65535); +} + +#[test] +fn test_Integer_u16_Min_Value() { + let src = "0:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u16_Overflow() { + let src = "65536:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u16_Underflow() { + let src = "-1:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u32_Decimal_Positive() { + let src = "42:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_u32_Zero() { + let src = "0:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u32_Hex() { + let src = "0xFF:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u32_Binary() { + let src = "0b1111:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_u32_Octal() { + let src = "0o77:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_u32_Max_Value() { + let src = "4294967295:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4294967295); +} + +#[test] +fn test_Integer_u32_Min_Value() { + let src = "0:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u32_Overflow() { + let src = "4294967296:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u32_Underflow() { + let src = "-1:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u32_With_Underscores() { + let src = "1_000_000:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_u64_Decimal_Positive() { + let src = "42:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_u64_Zero() { + let src = "0:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u64_Hex() { + let src = "0xFF:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u64_Binary() { + let src = "0b1111:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 15); +} + +#[test] +fn test_Integer_u64_Octal() { + let src = "0o77:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Integer_u64_Max_Value() { + let src = "18446744073709551615:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, UINT64_MAX); +} + +#[test] +fn test_Integer_u64_Min_Value() { + let src = "0:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Integer_u64_Overflow() { + let src = "18446744073709551616:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u64_Underflow() { + let src = "-1:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Integer_u64_With_Underscores() { + let src = "1_000_000:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_i8_Hex_Max() { + let src = "0x7F:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 127); +} + +#[test] +fn test_Integer_i8_Binary_Max() { + let src = "0b01111111:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 127); +} + +#[test] +fn test_Integer_i8_Octal_Max() { + let src = "0o177:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 127); +} + +#[test] +fn test_Integer_i8_Negative_Hex() { + let src = "-0x80:i8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -128); +} + +#[test] +fn test_Integer_u8_Hex_Max() { + let src = "0xFF:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u8_Binary_Max() { + let src = "0b11111111:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_u8_Octal_Max() { + let src = "0o377:u8"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_i16_Hex_Sample() { + let src = "0x1234:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4660); +} + +#[test] +fn test_Integer_i16_Binary_Sample() { + let src = "0b1111111100000000:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, -256); +} + +#[test] +fn test_Integer_i16_Octal_Sample() { + let src = "0o1234:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 668); +} + +#[test] +fn test_Integer_u16_Hex_Max() { + let src = "0xFFFF:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 65535); +} + +#[test] +fn test_Integer_u16_Binary_Max() { + let src = "0b1111111111111111:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 65535); +} + +#[test] +fn test_Integer_u16_Octal_Max() { + let src = "0o177777:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 65535); +} + +#[test] +fn test_Integer_u16_Decimal_Mid() { + let src = "50000:u16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 50000); +} + +#[test] +fn test_Integer_i32_Hex_Sample() { + let src = "0xABCD:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 43981); +} + +#[test] +fn test_Integer_i32_Binary_Sample() { + let src = "0b11110000:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 240); +} + +#[test] +fn test_Integer_u32_Hex_Max() { + let src = "0xFFFFFFFF:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4294967295); +} + +#[test] +fn test_Integer_u32_Binary_Sample() { + let src = "0b11111111000000001111111100000000:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4278255360); +} + +#[test] +fn test_Integer_u32_Octal_Max() { + let src = "0o37777777777:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4294967295); +} + +#[test] +fn test_Integer_u32_Decimal_Mid() { + let src = "1000000:u32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1000000); +} + +#[test] +fn test_Integer_i64_Decimal_Positive_42() { + let src = "42:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_i64_Hex_0xFF() { + let src = "0xFF:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 255); +} + +#[test] +fn test_Integer_i64_Binary_0b1010() { + let src = "0b1010:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 10); +} + +#[test] +fn test_Integer_i64_Octal_0o755() { + let src = "0o755:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 493); +} + +#[test] +fn test_Integer_u64_Hex_Max() { + let src = "0xFFFFFFFFFFFFFFFF:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, UINT64_MAX); +} + +#[test] +fn test_Integer_u64_Binary_Sample() { + let src = "0b1010101010101010:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 43690); +} + +#[test] +fn test_Integer_u64_Octal_Sample() { + let src = "0o7777:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 4095); +} + +#[test] +fn test_Integer_u64_Decimal() { + let src = "42:u64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Integer_Hex_With_Underscores() { + let src = "0xDEAD_BEEF:i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 3735928559); +} + +#[test] +fn test_Integer_Binary_With_Underscores() { + let src = "0b1111_0000_1010_0101:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 61605); +} + +#[test] +fn test_Integer_Octal_With_Underscores() { + let src = "0o7_7_7:i16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 511); +} + +#[test] +fn test_Float_Default_Simple() { + let src = "3.14"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Zero() { + let src = "0.0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 0.0).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Negative() { + let src = "-2.5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - -2.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_One() { + let src = "1.0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.0).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Simple() { + let src = "3.14:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_f64_Simple() { + let src = "2.718:f64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 2.718).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Leading_Zeros() { + let src = "00042.5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 42.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Leading_Zero_Decimal() { + let src = "0.5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 0.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Trailing_Zeros() { + let src = "3.1400"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_No_Leading_Digit() { + let src = ".5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 0.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_No_Leading_Digit_Negative() { + let src = "-.25"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - -0.25).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_No_Trailing_Digits() { + let src = "42."; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 42.0).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_No_Trailing_Digits_Negative() { + let src = "-7."; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - -7.0).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Very_Small() { + let src = "0.000001"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1e-06).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Very_Large() { + let src = "1000000.0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1000000.0).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Underscore_Integer_Part() { + let src = "1_000_000.5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1000000.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Underscore_Decimal_Part() { + let src = "3.141_592_653"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.141592653).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Underscore_Both_Parts() { + let src = "1_234.567_89"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1234.56789).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Underscore_Trailing() { + let src = "42.5_"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 42.5).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Underscore_Double() { + let src = "4__2.5"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 42.5).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_With_Underscores() { + let src = "1_234.567_89:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1234.56789).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Precision_Limit() { + let src = "1.2345678:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.2345678).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_High_Precision() { + let src = "3.141592653589793:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.141592653589793).abs() < 1e-12); +} + +#[test] +fn test_Float_f64_Precision_Limit() { + let src = "1.234567890123456:f64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.234567890123456).abs() < 1e-12); +} + +#[test] +fn test_Float_f64_High_Precision() { + let src = "3.141592653589793238:f64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.141592653589793).abs() < 1e-12); +} + +#[test] +fn test_Float_f64_Close_Numbers_1() { + let src = "1.0000000000000001:f64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.0).abs() < 1e-12); +} + +#[test] +fn test_Float_f64_Close_Numbers_2() { + let src = "1.0000000000000002:f64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.0000000000000002).abs() < 1e-12); +} + +#[test] +fn test_Float_Invalid_Multiple_Decimal_Points() { + let src = "3.14.159"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Float_Invalid_Characters() { + let src = "3.1a4"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Float_Invalid_Type_Annotation() { + let src = "3.14:i32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Float_Invalid_Type_Name() { + let src = "3.14:f16"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Float_Invalid_Comma_Separator() { + let src = "1,234.56"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Float_Default_Leading_Whitespace() { + let src = " 3.14"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Trailing_Whitespace() { + let src = "3.14 "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Both_Whitespace() { + let src = " 3.14 "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.14).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_With_Whitespace() { + let src = " 2.718:f32 "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 2.718).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Pi_Approximate() { + let src = "3.141592653589793"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.141592653589793).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Pi_Approximate() { + let src = "3.1415927:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 3.1415927).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Euler_Approximate() { + let src = "2.718281828459045"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 2.718281828459045).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Euler_Approximate() { + let src = "2.7182817:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 2.7182817).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Golden_Ratio() { + let src = "1.618033988749895"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.618033988749895).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Sqrt2() { + let src = "1.4142135623730951"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 1.4142135623730951).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Positive_Zero() { + let src = "0.0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 0.0).abs() < 1e-12); +} + +#[test] +fn test_Float_Default_Negative_Zero() { + let src = "-0.0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - -0.0).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Positive_Zero() { + let src = "0.0:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - 0.0).abs() < 1e-12); +} + +#[test] +fn test_Float_f32_Negative_Zero() { + let src = "-0.0:f32"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Float); + let parsed: f64 = got[0].lexeme.parse().expect("expected float"); + assert!((parsed - -0.0).abs() < 1e-12); +} + +#[test] +fn test_Char_Simple_Letter_A() { + let src = "'A'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 65); +} + +#[test] +fn test_Char_Simple_Letter_a() { + let src = "'a'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 97); +} + +#[test] +fn test_Char_Simple_Letter_Z() { + let src = "'Z'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 90); +} + +#[test] +fn test_Char_Simple_Letter_z() { + let src = "'z'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 122); +} + +#[test] +fn test_Char_Digit_0() { + let src = "'0'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 48); +} + +#[test] +fn test_Char_Digit_5() { + let src = "'5'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 53); +} + +#[test] +fn test_Char_Digit_9() { + let src = "'9'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 57); +} + +#[test] +fn test_Char_Space() { + let src = "' '"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 32); +} + +#[test] +fn test_Char_Exclamation() { + let src = "'!'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 33); +} + +#[test] +fn test_Char_Question_Mark() { + let src = "'?'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 63); +} + +#[test] +fn test_Char_Period() { + let src = "'.'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 46); +} + +#[test] +fn test_Char_Comma() { + let src = "','"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 44); +} + +#[test] +fn test_Char_Semicolon() { + let src = "';'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 59); +} + +#[test] +fn test_Char_Colon() { + let src = "':'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 58); +} + +#[test] +fn test_Char_Plus() { + let src = "'+'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 43); +} + +#[test] +fn test_Char_Minus() { + let src = "'-'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 45); +} + +#[test] +fn test_Char_Asterisk() { + let src = "'*'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 42); +} + +#[test] +fn test_Char_Slash() { + let src = "'/'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 47); +} + +#[test] +fn test_Char_Equals() { + let src = "'='"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 61); +} + +#[test] +fn test_Char_Less_Than() { + let src = "'<'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 60); +} + +#[test] +fn test_Char_Greater_Than() { + let src = "'>'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 62); +} + +#[test] +fn test_Char_Left_Paren() { + let src = "'('"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 40); +} + +#[test] +fn test_Char_Right_Paren() { + let src = "')'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 41); +} + +#[test] +fn test_Char_Left_Bracket() { + let src = "'['"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 91); +} + +#[test] +fn test_Char_Right_Bracket() { + let src = "']'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 93); +} + +#[test] +fn test_Char_Left_Brace() { + let src = "'{'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 123); +} + +#[test] +fn test_Char_Right_Brace() { + let src = "'}'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 125); +} + +#[test] +fn test_Char_Escape_Tab() { + let src = "'\\\\t'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 9); +} + +#[test] +fn test_Char_Escape_Backslash() { + let src = "'\\\\\\\\'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 92); +} + +#[test] +fn test_Char_Escape_Null_character() { + let src = "'\\\\0'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Char_Escape_Single_quote() { + let src = "'\\\\''"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 39); +} + +#[test] +fn test_Char_Escape_Carriage_return() { + let src = "'\\\\r'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 13); +} + +#[test] +fn test_Char_Escape_Newline() { + let src = "'\\\\n'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 10); +} + +#[test] +fn test_Char_With_Leading_Whitespace() { + let src = " 'A'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 65); +} + +#[test] +fn test_Char_With_Trailing_Whitespace() { + let src = "'A' "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 65); +} + +#[test] +fn test_Char_With_Both_Whitespace() { + let src = " 'A' "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 65); +} + +#[test] +fn test_Char_Tab_Before() { + let src = "\\t'B'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 66); +} + +#[test] +fn test_Char_Newline_Before() { + let src = "\\n'C'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected char code"); + assert_eq!(parsed, 67); +} + +#[test] +fn test_Char_Empty_Literal() { + let src = "''"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Char_Multiple_Characters() { + let src = "'AB'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Char_Unclosed_Quote() { + let src = "'A"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Char_Unescaped_Newline() { + let src = "'\\n'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Char_Invalid_Escape() { + let src = "'\\\\q'"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Identifier_Simple_Lowercase() { + let src = "hello"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Simple_Uppercase() { + let src = "HELLO"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "HELLO"); +} + +#[test] +fn test_Identifier_Mixed_Case() { + let src = "HelloWorld"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "HelloWorld"); +} + +#[test] +fn test_Identifier_Single_Letter() { + let src = "x"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "x"); +} + +#[test] +fn test_Identifier_Single_Letter_Upper() { + let src = "X"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "X"); +} + +#[test] +fn test_Identifier_With_Numbers() { + let src = "var123"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "var123"); +} + +#[test] +fn test_Identifier_Numbers_End() { + let src = "myVar2"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "myVar2"); +} + +#[test] +fn test_Identifier_Mixed_Numbers() { + let src = "a1b2c3"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "a1b2c3"); +} + +#[test] +fn test_Identifier_With_Underscore() { + let src = "hello_world"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello_world"); +} + +#[test] +fn test_Identifier_Leading_Underscore() { + let src = "_private"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "_private"); +} + +#[test] +fn test_Identifier_Multiple_Underscores() { + let src = "my_long_var_name"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my_long_var_name"); +} + +#[test] +fn test_Identifier_Double_Underscore() { + let src = "my__var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my__var"); +} + +#[test] +fn test_Identifier_Trailing_Underscore() { + let src = "var_"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "var_"); +} + +#[test] +fn test_Identifier_Only_Underscores() { + let src = "___"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "___"); +} + +#[test] +fn test_Identifier_Snake_Case() { + let src = "my_variable_name"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my_variable_name"); +} + +#[test] +fn test_Identifier_Camel_Case() { + let src = "myVariableName"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "myVariableName"); +} + +#[test] +fn test_Identifier_Pascal_Case() { + let src = "MyClassName"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "MyClassName"); +} + +#[test] +fn test_Identifier_All_Caps() { + let src = "MY_CONSTANT"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "MY_CONSTANT"); +} + +#[test] +fn test_Identifier_With_Dash() { + let src = "my-var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my-var"); +} + +#[test] +fn test_Identifier_Literal_Simple() { + let src = "::hello"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Literal_Uppercase() { + let src = "::Point"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "Point"); +} + +#[test] +fn test_Identifier_Literal_Snake_Case() { + let src = "::my_var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my_var"); +} + +#[test] +fn test_Identifier_Literal_Type_i64() { + let src = "::i64"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "i64"); +} + +#[test] +fn test_Identifier_Literal_Type_String() { + let src = "::String"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "String"); +} + +#[test] +fn test_Identifier_Literal_Type_Point() { + let src = "::Point"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "Point"); +} + +#[test] +fn test_Identifier_Literal_Trait_Addable() { + let src = "::Addable"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "Addable"); +} + +#[test] +fn test_Identifier_Literal_Trait_Drawable() { + let src = "::Drawable"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "Drawable"); +} + +#[test] +fn test_Identifier_Literal_Field_x() { + let src = "::x"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "x"); +} + +#[test] +fn test_Identifier_Literal_Field_width() { + let src = "::width"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "width"); +} + +#[test] +fn test_Identifier_Literal_With_Underscore() { + let src = "::_private"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "_private"); +} + +#[test] +fn test_Identifier_Literal_Multiple_Underscores() { + let src = "::my_long_name"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my_long_name"); +} + +#[test] +fn test_Identifier_Literal_With_Numbers() { + let src = "::var123"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "var123"); +} + +#[test] +fn test_Identifier_Leading_Whitespace() { + let src = " hello"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Trailing_Whitespace() { + let src = "hello "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Both_Whitespace() { + let src = " hello "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Tab_Before() { + let src = "\\thello"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Literal_Leading_Whitespace() { + let src = " ::hello"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Literal_Trailing_Whitespace() { + let src = "::hello "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Literal_Both_Whitespace() { + let src = " ::hello "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "hello"); +} + +#[test] +fn test_Identifier_Moderate_Length() { + let src = "thisIsAReasonablyLongVariableName"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "thisIsAReasonablyLongVariableName"); +} + +#[test] +fn test_Identifier_Very_Long() { + let src = "this_is_a_very_long_identifier_name_that_someone_might_use_for_some_reason"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "this_is_a_very_long_identifier_name_that_someone_might_use_for_some_reason"); +} + +#[test] +fn test_Identifier_Long_With_Numbers() { + let src = "variable_with_many_numbers_123_456_789_000"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "variable_with_many_numbers_123_456_789_000"); +} + +#[test] +fn test_Identifier_Starting_With_Number() { + let src = "123abc"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Identifier_With_Octothorpe() { + let src = "my#var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "my"); +} + +#[test] +fn test_Identifier_With_Colon() { + let src = "my:var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Identifier_Double_Colon_Inside() { + let src = "my::var"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Identifier_Only_Numbers() { + let src = "123"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 123); +} + +#[test] +fn test_Identifier_Literal_Empty() { + let src = "::"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_Identifier_Case_Lower() { + let src = "variable"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "variable"); +} + +#[test] +fn test_Identifier_Case_Upper() { + let src = "VARIABLE"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "VARIABLE"); +} + +#[test] +fn test_Identifier_Case_Mixed() { + let src = "Variable"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "Variable"); +} + +#[test] +fn test_Identifier_Case_Camel() { + let src = "variableName"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "variableName"); +} + +#[test] +fn test_Identifier_Case_Pascal() { + let src = "VariableName"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "VariableName"); +} + +#[test] +fn test_Identifier_Reserved_Word_if() { + let src = "if"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "if"); +} + +#[test] +fn test_Identifier_Reserved_Word_while() { + let src = "while"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "while"); +} + +#[test] +fn test_Identifier_Reserved_Word_for() { + let src = "for"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "for"); +} + +#[test] +fn test_Identifier_Reserved_Word_match() { + let src = "match"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "match"); +} + +#[test] +fn test_Identifier_Reserved_Word_break() { + let src = "break"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "break"); +} + +#[test] +fn test_Identifier_Reserved_Word_continue() { + let src = "continue"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "continue"); +} + +#[test] +fn test_Identifier_Reserved_Word_fn() { + let src = "fn"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "fn"); +} + +#[test] +fn test_Identifier_Reserved_Word_struct() { + let src = "struct"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "struct"); +} + +#[test] +fn test_Identifier_Reserved_Word_union() { + let src = "union"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "union"); +} + +#[test] +fn test_Identifier_Reserved_Word_enum() { + let src = "enum"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "enum"); +} + +#[test] +fn test_Identifier_Reserved_Word_trait() { + let src = "trait"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "trait"); +} + +#[test] +fn test_Identifier_Reserved_Word_impl() { + let src = "impl"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "impl"); +} + +#[test] +fn test_Identifier_Reserved_Word_inher() { + let src = "inher"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "inher"); +} + +#[test] +fn test_Identifier_Reserved_Word_dup() { + let src = "dup"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "dup"); +} + +#[test] +fn test_Identifier_Reserved_Word_drop() { + let src = "drop"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "drop"); +} + +#[test] +fn test_Identifier_Reserved_Word_swap() { + let src = "swap"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "swap"); +} + +#[test] +fn test_Identifier_Reserved_Word_over() { + let src = "over"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "over"); +} + +#[test] +fn test_Identifier_Reserved_Word_rot() { + let src = "rot"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "rot"); +} + +#[test] +fn test_Identifier_Reserved_Word_pick() { + let src = "pick"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "pick"); +} + +#[test] +fn test_Identifier_Reserved_Word_roll() { + let src = "roll"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "roll"); +} + +#[test] +fn test_Identifier_Reserved_Word_depth() { + let src = "depth"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "depth"); +} + +#[test] +fn test_Bool_True() { + let src = "true"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); +} + +#[test] +fn test_Bool_False() { + let src = "false"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "false"); +} + +#[test] +fn test_Bool_True_Leading_Whitespace() { + let src = " true"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); +} + +#[test] +fn test_Bool_True_Trailing_Whitespace() { + let src = "true "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); +} + +#[test] +fn test_Bool_True_Both_Whitespace() { + let src = " true "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); +} + +#[test] +fn test_Bool_True_Tab_Before() { + let src = "\\ttrue"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); +} + +#[test] +fn test_Bool_False_Leading_Whitespace() { + let src = " false"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "false"); +} + +#[test] +fn test_Bool_False_Trailing_Whitespace() { + let src = "false "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "false"); +} + +#[test] +fn test_Bool_False_Both_Whitespace() { + let src = " false "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "false"); +} + +#[test] +fn test_Bool_False_Tab_Before() { + let src = "\\tfalse"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "false"); +} + +#[test] +fn test_Bool_True_Capitalized() { + let src = "True"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "True"); +} + +#[test] +fn test_Bool_False_Capitalized() { + let src = "False"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "False"); +} + +#[test] +fn test_Bool_True_All_Caps() { + let src = "TRUE"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "TRUE"); +} + +#[test] +fn test_Bool_False_All_Caps() { + let src = "FALSE"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "FALSE"); +} + +#[test] +fn test_Bool_True_Mixed_Case() { + let src = "tRuE"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "tRuE"); +} + +#[test] +fn test_Bool_False_Mixed_Case() { + let src = "fAlSe"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "fAlSe"); +} + +#[test] +fn test_Bool_Numeric_1() { + let src = "1"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 1); +} + +#[test] +fn test_Bool_Numeric_0() { + let src = "0"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Int); + let parsed: i128 = got[0].lexeme.parse().expect("expected integer"); + assert_eq!(parsed, 0); +} + +#[test] +fn test_Bool_Yes() { + let src = "yes"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "yes"); +} + +#[test] +fn test_Bool_No() { + let src = "no"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "no"); +} + +#[test] +fn test_Bool_Typo_Ture() { + let src = "ture"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "ture"); +} + +#[test] +fn test_Bool_Typo_Flase() { + let src = "flase"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "flase"); +} + +#[test] +fn test_Bool_Multiple_True_False() { + let src = "true false"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 2usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); + assert_eq!(got[1].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[1].lexeme, "false"); +} + +#[test] +fn test_Bool_Multiple_Same() { + let src = "true true"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 2usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); + assert_eq!(got[1].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[1].lexeme, "true"); +} + +#[test] +fn test_Bool_Three_Values() { + let src = "true false true"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 3usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[0].lexeme, "true"); + assert_eq!(got[1].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[1].lexeme, "false"); + assert_eq!(got[2].ttype, sls::lexer::TokenType::Ident); + assert_eq!(got[2].lexeme, "true"); +} + +#[test] +fn test_TokenString_Empty() { + let src = "{ }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Single_Integer() { + let src = "{ 42 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Single_Identifier() { + let src = "{ dup }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Two_Integers() { + let src = "{ 2 3 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Simple_Expression() { + let src = "{ 2 3 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Stack_Ops() { + let src = "{ dup * }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Integer_Literals() { + let src = "{ 0 42 -10 1000 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Float_Literals() { + let src = "{ 3.14 -2.5 0.0 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Char_Literal() { + let src = "{ 'A' }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Boolean_Literals() { + let src = "{ true false }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiple_Identifiers() { + let src = "{ dup swap over }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Identifier_Literals() { + let src = "{ ::x ::y }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Mixed_Identifiers() { + let src = "{ ::Point get x swap }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Nested_Single() { + let src = "{ { 2 3 + } }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Nested_With_Others() { + let src = "{ x { dup * } }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiple_Nested() { + let src = "{ { 2 3 + } { 4 5 * } }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Double_Nested() { + let src = "{ { { 42 } } }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Complex_Nesting() { + let src = "{ 1 { 2 { 3 } 4 } 5 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_No_Whitespace() { + let src = "{2 3 +}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Extra_Whitespace() { + let src = "{ 2 3 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Leading_Whitespace_Outside() { + let src = " { 2 3 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Trailing_Whitespace_Outside() { + let src = "{ 2 3 + } "; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_With_Tabs() { + let src = "{\\t2\\t3\\t+\\t}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiline_Simple() { + let src = "{\\n 2 3 +\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiline_Multiple() { + let src = "{\\n dup\\n *\\n 2\\n +\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Mixed_Line_Breaks() { + let src = "{ 1 2\\n3 4\\n\\n5 6 }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Indented_Multiline() { + let src = "{\\n dup 0 >\\n { }\\n { 0 swap - }\\n if\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Comment_End_Of_Line() { + let src = "{ 2 3 + // add them\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiple_Comments() { + let src = "{ 2 // first\\n3 // second\\n+ // add\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Comment_Own_Line() { + let src = "{\\n // This is a comment\\n 2 3 +\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Comment_At_Start() { + let src = "{ // comment\\n2 3 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Multiple_Comment_Lines() { + let src = "{\\n // First comment\\n // Second comment\\n 2 3 +\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Comments_Nested() { + let src = "{ { 2 3 + // inner comment\\n} // outer comment\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Unclosed() { + let src = "{ 2 3 +"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_TokenString_Unclosed_Nested() { + let src = "{ { 2 3 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_TokenString_Extra_Closing_Brace() { + let src = "{ 2 3 + } }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 2usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); + assert_eq!(got[1].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_TokenString_Only_Closing_Brace() { + let src = "}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + assert_eq!(got[0].ttype, sls::lexer::TokenType::Illegal); +} + +#[test] +fn test_TokenString_Error_Inside() { + let src = "{ 2 3a + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Function_Body() { + let src = "{ dup * }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Loop_Body() { + let src = "{ dup print 1 + }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Struct_Fields() { + let src = "{ x: y: }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Lambda() { + let src = "{ 2 * }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Array_Map() { + let src = "{ dup * }"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} + +#[test] +fn test_TokenString_Conditional_Complex() { + let src = "{\\n dup 0 >\\n { dup * }\\n { drop 0 }\\n if\\n}"; + let mut lexer = sls::lexer::Lexer::new(src); + let mut got = vec![]; + loop { + let t = lexer.next_token(); + if t.ttype == sls::lexer::TokenType::Eof { break; } + got.push(t); + } + + assert_eq!(got.len(), 1usize, "token count mismatch"); + // token_string check not implemented; received token: {:#?} + // TODO: implement nested expectations + // for now just assert we got an Ident or similar + assert!(!got[0].lexeme.is_empty()); +} diff --git a/SLS_Tests/yaml_to_rust_tests.py b/SLS_Tests/yaml_to_rust_tests.py new file mode 100644 index 0000000..5dd9108 --- /dev/null +++ b/SLS_Tests/yaml_to_rust_tests.py @@ -0,0 +1,120 @@ +import yaml +import re +from pathlib import Path + +""" +Convert YAML test cases to Rust integration tests for the `sls` crate. + +Usage: + python3 SLS_Tests/yaml_to_rust_tests.py SLS_Tests/cases.yaml SLS_Rust/sls/tests/lexer_tests_generated.rs + +This generator produces simple `#[test]` functions that run the lexer and +verify token kinds and values (basic checks). It's intentionally conservative +— it compares token types and lexemes/numeric values where applicable. +""" + +def sanitize_name(name: str) -> str: + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + name = re.sub(r"_+", "_", name) + name = name.strip("_") + if not name: + name = "unnamed" + return f"test_{name}" + + +def rust_string_literal(s: str) -> str: + return s.replace('\\', '\\\\').replace('"', '\\"') + + +def token_match_expectation(token_var: str, expected: dict) -> str: + ttype = expected.get('type') + val = expected.get('value') + + if ttype in ('i64','i32','i16','i8','u64','u32','u16','u8'): + # parse integer from token.lexeme and compare + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Int);\n let parsed: i128 = {token_var}.lexeme.parse().expect(\"expected integer\");\n assert_eq!(parsed, {val});" + elif ttype in ('f64','f32'): + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Float);\n let parsed: f64 = {token_var}.lexeme.parse().expect(\"expected float\");\n assert!((parsed - {val}).abs() < 1e-12);" + elif ttype == 'string': + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Str);\n assert_eq!({token_var}.lexeme, \"{rust_string_literal(str(val))}\");" + elif ttype in ('identifier', 'identifier_literal'): + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Ident);\n assert_eq!({token_var}.lexeme, \"{rust_string_literal(str(val))}\");" + elif ttype == 'char': + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Int);\n let parsed: i128 = {token_var}.lexeme.parse().expect(\"expected char code\");\n assert_eq!(parsed, {(ord(val))});" # type: ignore + elif ttype == 'bool': + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Ident);\n assert_eq!({token_var}.lexeme, \"{'true' if val else 'false'}\");" + elif ttype == 'error': + # For now, assert that we got an Illegal token + return f"assert_eq!({token_var}.ttype, sls::lexer::TokenType::Illegal);" + elif ttype == 'token_string': + # Complex nested token strings are not handled by this simple generator + return f"// token_string check not implemented; received token: {{:#?}}\n // TODO: implement nested expectations\n // for now just assert we got an Ident or similar\n assert!(!{token_var}.lexeme.is_empty());" + else: + return f"// Unhandled expected token type: {ttype}\n assert!(!{token_var}.lexeme.is_empty());" + + +def generate_rust_test(test: dict) -> str: + name = sanitize_name(test.get('name','unnamed')) + code = test.get('code','') + tokens = test.get('tokens', []) + + fn_lines = [f"#[test]", f"fn {name}() " "{"] + fn_lines.append(f" let src = \"{rust_string_literal(str(code))}\";") + fn_lines.append(" let mut lexer = sls::lexer::Lexer::new(src);") + fn_lines.append(" let mut got = vec![];") + fn_lines.append(" loop {") + fn_lines.append(" let t = lexer.next_token();") + fn_lines.append(" if t.ttype == sls::lexer::TokenType::Eof { break; }") + fn_lines.append(" got.push(t);") + fn_lines.append(" }") + fn_lines.append("") + # Basic assertion count vs expected (allow zero expected -> empty) + if tokens: + fn_lines.append(f" assert_eq!(got.len(), {len(tokens)}usize, \"token count mismatch\");") + else: + fn_lines.append(" assert!(got.is_empty());") + + for i, token in enumerate(tokens): + expectation = token_match_expectation(f"got[{i}]", token) + # indent lines of expectation properly + for line in expectation.split('\n'): + fn_lines.append(f" {line}") + + fn_lines.append("}") + fn_lines.append("") + return "\n".join(fn_lines) + + +def yaml_to_rust_tests(yaml_path: str, output_path: str): + with open(yaml_path, 'r', encoding='utf-8') as f: + tests = yaml.safe_load(f) + + if not isinstance(tests, list): + raise ValueError('Expected YAML to be a list of tests') + + rust_tests = [] + for t in tests: + rust_tests.append(generate_rust_test(t)) + + header = """// Generated tests - do not edit by hand +// Use: run `python3 SLS_Tests/yaml_to_rust_tests.py SLS_Tests/cases.yaml tests/lexer_tests_generated.rs` + +use sls; // crate under test + +const INT64_MIN: i128 = i64::MIN as i128; +const UINT64_MAX: i128 = u64::MAX as i128; + +""" + + out_text = header + "\n".join(rust_tests) + Path(output_path).write_text(out_text, encoding='utf-8') + print(f"Generated {len(rust_tests)} Rust tests -> {output_path}") + + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('input') + parser.add_argument('output') + args = parser.parse_args() + yaml_to_rust_tests(args.input, args.output)