diff --git a/lang/src/lib.rs b/lang/src/lib.rs index daf0250..3d7553e 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -36,6 +36,7 @@ pub use fs::*; use { self::{ty::Builtin, utils::Ent}, alloc::vec::Vec, + core::{fmt::Arguments, format_args as fa}, }; #[macro_use] @@ -316,9 +317,9 @@ impl Ident { fn endoce_string( literal: &str, str: &mut Vec, - report: impl Fn(&core::str::Bytes, &str), + report: impl Fn(&core::str::Bytes, Arguments), ) -> Option { - let report = |bytes: &core::str::Bytes, msg: &_| { + let report = |bytes: &core::str::Bytes, msg: Arguments| { report(bytes, msg); None:: }; @@ -327,13 +328,13 @@ fn endoce_string( while let Some(b) = bytes.next() && b != b'}' { - let c = bytes.next().or_else(|| report(bytes, "incomplete escape sequence"))?; + let c = bytes.next().or_else(|| report(bytes, fa!("incomplete escape sequence")))?; let decode = |b: u8| { Some(match b { b'0'..=b'9' => b - b'0', b'a'..=b'f' => b - b'a' + 10, b'A'..=b'F' => b - b'A' + 10, - _ => report(bytes, "expected hex digit or '}'")?, + _ => report(bytes, fa!("expected hex digit or '}}'"))?, }) }; str.push(decode(b)? << 4 | decode(c)?); @@ -350,19 +351,27 @@ fn endoce_string( str.push(b); continue; } - let b = match bytes.next().or_else(|| report(&bytes, "incomplete escape sequence"))? { - b'n' => b'\n', - b'r' => b'\r', - b't' => b'\t', - b'\\' => b'\\', - b'\'' => b'\'', - b'"' => b'"', - b'0' => b'\0', + + const SPECIAL_CHARS: &str = "nrt\\'\"0"; + const TO_BYTES: &[u8] = b"\n\r\t\\'\"\0"; + const _: () = assert!(SPECIAL_CHARS.len() == TO_BYTES.len()); + + let b = match bytes.next().or_else(|| report(&bytes, fa!("incomplete escape sequence")))? { + b if let Some((_, &i)) = SPECIAL_CHARS.bytes().zip(TO_BYTES).find(|&(i, _)| i == b) => { + i + } b'{' => { decode_braces(str, &mut bytes); continue; } - _ => report(&bytes, "unknown escape sequence, expected [nrt\\\"'{0]")?, + _ => report( + &bytes, + format_args!( + "unknown escape sequence, \ + expected one of special characters (regex /[{SPECIAL_CHARS}]/), \ + or arbitrary byte sequence in hex (regex /\\{{[0-9a-f]{{2}}+\\/}})" + ), + )?, }; str.push(b); } diff --git a/lang/src/son.rs b/lang/src/son.rs index 4761371..ec8fab4 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -28,7 +28,7 @@ use { assert_matches::debug_assert_matches, cell::RefCell, error, - fmt::{self, Debug, Display, Write}, + fmt::{self, Arguments, Debug, Display, Write}, format_args as fa, mem, }, }; @@ -887,7 +887,7 @@ impl<'a> Codegen<'a> { let mut data = core::mem::take(&mut self.pool.lit_buf); debug_assert!(data.is_empty()); - let report = |bytes: &core::str::Bytes, message: &str| { + let report = |bytes: &core::str::Bytes, message: Arguments| { self.error(pos + (literal.len() - bytes.len()) as u32 - 1, message); };