6649: Accept more than just the standard rust literal suffixes in *Number::suffix r=matklad a=Veykril

I am not entirely sure whether to keep or remove the `SUFFIXES` but I figured we can always bring them back once they are needed.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot]
2020-12-02 13:13:01 +00:00
committed by GitHub

View File

@@ -543,11 +543,6 @@ impl HasFormatSpecifier for ast::String {
} }
impl ast::IntNumber { impl ast::IntNumber {
const SUFFIXES: &'static [&'static str] = &[
"u8", "u16", "u32", "u64", "u128", "usize", // Unsigned.
"i8", "i16", "i32", "i64", "i128", "isize", // Signed.
];
pub fn radix(&self) -> Radix { pub fn radix(&self) -> Radix {
match self.text().get(..2).unwrap_or_default() { match self.text().get(..2).unwrap_or_default() {
"0b" => Radix::Binary, "0b" => Radix::Binary,
@@ -580,29 +575,30 @@ impl ast::IntNumber {
pub fn suffix(&self) -> Option<&str> { pub fn suffix(&self) -> Option<&str> {
let text = self.text(); let text = self.text();
// FIXME: don't check a fixed set of suffixes, `1_0_1_l_o_l` is valid let radix = self.radix();
// syntax, suffix is `l_o_l`. let mut indices = text.char_indices();
ast::IntNumber::SUFFIXES.iter().chain(ast::FloatNumber::SUFFIXES.iter()).find_map( if radix != Radix::Decimal {
|suffix| { indices.next()?;
if text.ends_with(suffix) { indices.next()?;
return Some(&text[text.len() - suffix.len()..]); }
} let is_suffix_start: fn(&(usize, char)) -> bool = match radix {
None Radix::Hexadecimal => |(_, c)| matches!(c, 'g'..='z' | 'G'..='Z'),
}, _ => |(_, c)| c.is_ascii_alphabetic(),
) };
let (suffix_start, _) = indices.find(is_suffix_start)?;
Some(&text[suffix_start..])
} }
} }
impl ast::FloatNumber { impl ast::FloatNumber {
const SUFFIXES: &'static [&'static str] = &["f32", "f64"];
pub fn suffix(&self) -> Option<&str> { pub fn suffix(&self) -> Option<&str> {
let text = self.text(); let text = self.text();
ast::FloatNumber::SUFFIXES.iter().find_map(|suffix| { let mut indices = text.char_indices();
if text.ends_with(suffix) { let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?;
return Some(&text[text.len() - suffix.len()..]); if c == 'e' || c == 'E' {
} suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0;
None }
}) Some(&text[suffix_start..])
} }
} }
@@ -625,3 +621,40 @@ impl Radix {
} }
} }
} }
#[cfg(test)]
mod tests {
use crate::ast::{make, FloatNumber, IntNumber};
fn check_float_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into());
}
fn check_int_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into());
}
#[test]
fn test_float_number_suffix() {
check_float_suffix("123.0", None);
check_float_suffix("123f32", "f32");
check_float_suffix("123.0e", None);
check_float_suffix("123.0e4", None);
check_float_suffix("123.0ef32", "f32");
check_float_suffix("123.0E4f32", "f32");
check_float_suffix("1_2_3.0_f32", "f32");
}
#[test]
fn test_int_number_suffix() {
check_int_suffix("123", None);
check_int_suffix("123i32", "i32");
check_int_suffix("1_0_1_l_o_l", "l_o_l");
check_int_suffix("0b11", None);
check_int_suffix("0o11", None);
check_int_suffix("0xff", None);
check_int_suffix("0b11u32", "u32");
check_int_suffix("0o11u32", "u32");
check_int_suffix("0xffu32", "u32");
}
}