diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-02 13:13:01 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-02 13:13:01 +0000 |
commit | dc09d97fb2f4c7f938a76b4ba7b0b483f96ceb5d (patch) | |
tree | 1542f7e75a912f40a4dcc1b1bbca3e62f8ad3cfc /crates/syntax/src/ast | |
parent | 1db60512b63165e0a4b6c525d26020830f5057bb (diff) | |
parent | 49fbfffb48a5926cd4a01ca6b23f656a84fec830 (diff) |
Merge #6649
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 <[email protected]>
Diffstat (limited to 'crates/syntax/src/ast')
-rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 77 |
1 files changed, 55 insertions, 22 deletions
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index b985861f2..fa40e64e8 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -543,11 +543,6 @@ impl HasFormatSpecifier for ast::String { | |||
543 | } | 543 | } |
544 | 544 | ||
545 | impl ast::IntNumber { | 545 | impl ast::IntNumber { |
546 | const SUFFIXES: &'static [&'static str] = &[ | ||
547 | "u8", "u16", "u32", "u64", "u128", "usize", // Unsigned. | ||
548 | "i8", "i16", "i32", "i64", "i128", "isize", // Signed. | ||
549 | ]; | ||
550 | |||
551 | pub fn radix(&self) -> Radix { | 546 | pub fn radix(&self) -> Radix { |
552 | match self.text().get(..2).unwrap_or_default() { | 547 | match self.text().get(..2).unwrap_or_default() { |
553 | "0b" => Radix::Binary, | 548 | "0b" => Radix::Binary, |
@@ -580,29 +575,30 @@ impl ast::IntNumber { | |||
580 | 575 | ||
581 | pub fn suffix(&self) -> Option<&str> { | 576 | pub fn suffix(&self) -> Option<&str> { |
582 | let text = self.text(); | 577 | let text = self.text(); |
583 | // FIXME: don't check a fixed set of suffixes, `1_0_1_l_o_l` is valid | 578 | let radix = self.radix(); |
584 | // syntax, suffix is `l_o_l`. | 579 | let mut indices = text.char_indices(); |
585 | ast::IntNumber::SUFFIXES.iter().chain(ast::FloatNumber::SUFFIXES.iter()).find_map( | 580 | if radix != Radix::Decimal { |
586 | |suffix| { | 581 | indices.next()?; |
587 | if text.ends_with(suffix) { | 582 | indices.next()?; |
588 | return Some(&text[text.len() - suffix.len()..]); | 583 | } |
589 | } | 584 | let is_suffix_start: fn(&(usize, char)) -> bool = match radix { |
590 | None | 585 | Radix::Hexadecimal => |(_, c)| matches!(c, 'g'..='z' | 'G'..='Z'), |
591 | }, | 586 | _ => |(_, c)| c.is_ascii_alphabetic(), |
592 | ) | 587 | }; |
588 | let (suffix_start, _) = indices.find(is_suffix_start)?; | ||
589 | Some(&text[suffix_start..]) | ||
593 | } | 590 | } |
594 | } | 591 | } |
595 | 592 | ||
596 | impl ast::FloatNumber { | 593 | impl ast::FloatNumber { |
597 | const SUFFIXES: &'static [&'static str] = &["f32", "f64"]; | ||
598 | pub fn suffix(&self) -> Option<&str> { | 594 | pub fn suffix(&self) -> Option<&str> { |
599 | let text = self.text(); | 595 | let text = self.text(); |
600 | ast::FloatNumber::SUFFIXES.iter().find_map(|suffix| { | 596 | let mut indices = text.char_indices(); |
601 | if text.ends_with(suffix) { | 597 | let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?; |
602 | return Some(&text[text.len() - suffix.len()..]); | 598 | if c == 'e' || c == 'E' { |
603 | } | 599 | suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0; |
604 | None | 600 | } |
605 | }) | 601 | Some(&text[suffix_start..]) |
606 | } | 602 | } |
607 | } | 603 | } |
608 | 604 | ||
@@ -625,3 +621,40 @@ impl Radix { | |||
625 | } | 621 | } |
626 | } | 622 | } |
627 | } | 623 | } |
624 | |||
625 | #[cfg(test)] | ||
626 | mod tests { | ||
627 | use crate::ast::{make, FloatNumber, IntNumber}; | ||
628 | |||
629 | fn check_float_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) { | ||
630 | assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into()); | ||
631 | } | ||
632 | |||
633 | fn check_int_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) { | ||
634 | assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into()); | ||
635 | } | ||
636 | |||
637 | #[test] | ||
638 | fn test_float_number_suffix() { | ||
639 | check_float_suffix("123.0", None); | ||
640 | check_float_suffix("123f32", "f32"); | ||
641 | check_float_suffix("123.0e", None); | ||
642 | check_float_suffix("123.0e4", None); | ||
643 | check_float_suffix("123.0ef32", "f32"); | ||
644 | check_float_suffix("123.0E4f32", "f32"); | ||
645 | check_float_suffix("1_2_3.0_f32", "f32"); | ||
646 | } | ||
647 | |||
648 | #[test] | ||
649 | fn test_int_number_suffix() { | ||
650 | check_int_suffix("123", None); | ||
651 | check_int_suffix("123i32", "i32"); | ||
652 | check_int_suffix("1_0_1_l_o_l", "l_o_l"); | ||
653 | check_int_suffix("0b11", None); | ||
654 | check_int_suffix("0o11", None); | ||
655 | check_int_suffix("0xff", None); | ||
656 | check_int_suffix("0b11u32", "u32"); | ||
657 | check_int_suffix("0o11u32", "u32"); | ||
658 | check_int_suffix("0xffu32", "u32"); | ||
659 | } | ||
660 | } | ||