]> git.lizzy.rs Git - rust.git/commitdiff
negative sign matching in mbe matching for literal
authorEdwin Cheng <edwin0cheng@gmail.com>
Fri, 11 Dec 2020 09:59:04 +0000 (17:59 +0800)
committerEdwin Cheng <edwin0cheng@gmail.com>
Fri, 11 Dec 2020 09:59:04 +0000 (17:59 +0800)
crates/mbe/src/mbe_expander/matcher.rs
crates/mbe/src/tests.rs

index 3f844589778ae9ff50272bf0366b7ae10718e3ba..4860b242d007a9f46ad81b14a6f0f68274eb4c38 100644 (file)
@@ -356,6 +356,18 @@ pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
             ExpandResult { value: _, err: Some(_) } => None,
         }
     }
+
+    pub(crate) fn eat_char(&mut self) -> Option<tt::TokenTree> {
+        let mut fork = self.clone();
+        match fork.expect_char('-') {
+            Ok(_) => {
+                let tt = self.next().cloned();
+                *self = fork;
+                tt
+            }
+            Err(_) => None,
+        }
+    }
 }
 
 pub(super) fn match_repeat(
@@ -447,10 +459,22 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen
                     .expect_lifetime()
                     .map(|tt| Some(tt))
                     .map_err(|()| err!("expected lifetime")),
-                "literal" => input
-                    .expect_literal()
-                    .map(|literal| Some(tt::Leaf::from(literal.clone()).into()))
-                    .map_err(|()| err!()),
+                "literal" => {
+                    let neg = input.eat_char();
+                    input
+                        .expect_literal()
+                        .map(|literal| {
+                            let lit = tt::Leaf::from(literal.clone());
+                            match neg {
+                                None => Some(lit.into()),
+                                Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree {
+                                    delimiter: None,
+                                    token_trees: vec![neg, lit.into()],
+                                })),
+                            }
+                        })
+                        .map_err(|()| err!())
+                }
                 // `vis` is optional
                 "vis" => match input.eat_vis() {
                     Some(vis) => Ok(Some(vis)),
index 0796ceee1a7a7306c2004ceea592fa28ee5a22f4..843054fe854933c10b434d9add3ee1b5efc0bcac 100644 (file)
@@ -1008,11 +1008,20 @@ fn test_literal() {
     parse_macro(
         r#"
         macro_rules! foo {
-              ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;};
+              ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;};
         }
 "#,
     )
-    .assert_expand_items(r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#);
+    .assert_expand_items(r#"foo!(u8,0);"#, r#"const VALUE : u8 = 0 ;"#);
+
+    parse_macro(
+        r#"
+        macro_rules! foo {
+              ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;};
+        }
+"#,
+    )
+    .assert_expand_items(r#"foo!(i32,-1);"#, r#"const VALUE : i32 = - 1 ;"#);
 }
 
 #[test]