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(
.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)),
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]