From: Bryan English Date: Sat, 28 Mar 2026 03:24:28 +0000 (-0400) Subject: support hex number literals X-Git-Url: https://rethought.computer/gitweb//gitweb//git?a=commitdiff_plain;h=77e98233f52d633b20bfd5f4117614098238a30b;p=sorel-lang.git support hex number literals --- diff --git a/sorel-parser/src/lib.rs b/sorel-parser/src/lib.rs index dd94d97..120243f 100644 --- a/sorel-parser/src/lib.rs +++ b/sorel-parser/src/lib.rs @@ -127,7 +127,7 @@ mod tests { #[test] fn try_some_parsing() { - let result = Module::parse(crate::tokenizer::tokenize(" + let result = Module::parse(sorel_tokenizer::tokenize(" : hello world 16 \"planet\" ; : soup chicken 4.5 hello ; diff --git a/sorel-tokenizer/src/lib.rs b/sorel-tokenizer/src/lib.rs index 06dac68..86c2b42 100644 --- a/sorel-tokenizer/src/lib.rs +++ b/sorel-tokenizer/src/lib.rs @@ -1,4 +1,5 @@ use anyhow::{Result, anyhow}; +use std::str::FromStr; #[derive(Debug, Clone)] pub enum Token<'a> { @@ -16,6 +17,41 @@ pub enum Token<'a> { NumF64(f64), } +trait IntFromStrRadix { + fn from_radix(src: &str, radix: u32) -> Result where Self: Sized; +} + +macro_rules! radix_impl { + ($type:ty) => { + impl IntFromStrRadix for $type { + fn from_radix(src: &str, radix: u32) -> Result { + <$type>::from_str_radix(src, radix) + .map_err(|_| anyhow!("parse error for number: {}", src)) + } + } + }; + ($typ1:ty, $($typ2:ty),+) => { + radix_impl!($typ1); + radix_impl!($($typ2),+); + }; +} + +radix_impl!(u8, i8, u16, i16, u32, i32, u64, i64); + +fn parse_int(num: &str) -> Result { + let mut radix = 10; + let mut num_cleaned = num; + if num.starts_with("0x") { + radix = 16; + num_cleaned = &num[2..]; + } + T::from_radix(num_cleaned, radix) +} + +fn parse_float(num: &str) -> Result { + num.parse().map_err(|_| anyhow!("parse error for number: {}", num)) +} + impl<'a> Token<'a>{ fn parse_word_or_num(input: &'a str) -> Result> { if input == "-" { @@ -30,24 +66,24 @@ impl<'a> Token<'a>{ let num = splat.next().ok_or(anyhow!("no number found"))?; let typ = splat.next().ok_or(anyhow!("no number type found"))?; match typ { - "u8" => Ok(Token::NumU8(num.parse()?)), - "i8" => Ok(Token::NumI8(num.parse()?)), - "u16" => Ok(Token::NumU16(num.parse()?)), - "i16" => Ok(Token::NumI16(num.parse()?)), - "u32" => Ok(Token::NumU32(num.parse()?)), - "i32" => Ok(Token::NumI32(num.parse()?)), - "u64" => Ok(Token::NumU64(num.parse()?)), - "i64" => Ok(Token::NumI64(num.parse()?)), - "f32" => Ok(Token::NumF32(num.parse()?)), - "f64" => Ok(Token::NumF64(num.parse()?)), + "u8" => Ok(Token::NumU8(parse_int(num)?)), + "i8" => Ok(Token::NumI8(parse_int(num)?)), + "u16" => Ok(Token::NumU16(parse_int(num)?)), + "i16" => Ok(Token::NumI16(parse_int(num)?)), + "u32" => Ok(Token::NumU32(parse_int(num)?)), + "i32" => Ok(Token::NumI32(parse_int(num)?)), + "u64" => Ok(Token::NumU64(parse_int(num)?)), + "i64" => Ok(Token::NumI64(parse_int(num)?)), + "f32" => Ok(Token::NumF32(parse_float(num)?)), + "f64" => Ok(Token::NumF64(parse_float(num)?)), _ => panic!("unknown number type") } } else if input.contains('.') { - Ok(Token::NumF64(input.parse()?)) + Ok(Token::NumF64(parse_float(input)?)) } else if input.starts_with('-') { - Ok(Token::NumI64(input.parse()?)) + Ok(Token::NumI64(parse_int(input)?)) } else { - Ok(Token::NumU64(input.parse()?)) + Ok(Token::NumU64(parse_int(input)?)) } } else { Ok(Token::Word(input)) @@ -155,7 +191,7 @@ mod tests { let result = tokenize(" \\ soup - 2 3.4 - -88 bacon \"hello\" 43:f32 2345:u32 -57:i8 soup + 2 0x10 3.4 - -88 bacon \"hello\" 43:f32 2345:u32 -57:i8 soup "); println!("result: {:?}", result); } diff --git a/stdlib/net.sorel b/stdlib/net.sorel new file mode 100644 index 0000000..403e4d3 --- /dev/null +++ b/stdlib/net.sorel @@ -0,0 +1,3 @@ +\ vim: filetype=forth + +