Macros 宏将非元组参数转换为元组
是否可以创建一个宏来将非元组参数转换为元组?我想要这样的东西:Macros 宏将非元组参数转换为元组,macros,rust,Macros,Rust,是否可以创建一个宏来将非元组参数转换为元组?我想要这样的东西: assert_eq!(tuplify!(1, (2, 3), 4), ((1,), (2, 3), (4,))); 我试图创建这样的宏,但无法做到这一点。我面临的问题是,每个参数可以有两种形式中的一种,而我不知道如何指定它。如果宏的每个参数都是一个标记树,那么这就可以: macro_rules! tuplify { (@inner ($($args:expr),*)) => (($($args,)*)); (
assert_eq!(tuplify!(1, (2, 3), 4), ((1,), (2, 3), (4,)));
我试图创建这样的宏,但无法做到这一点。我面临的问题是,每个参数可以有两种形式中的一种,而我不知道如何指定它。如果宏的每个参数都是一个标记树,那么这就可以:
macro_rules! tuplify {
(@inner ($($args:expr),*)) => (($($args,)*));
(@inner $arg:expr) => (($arg,));
($($arg:tt),*) => (($(tuplify!(@inner $arg),)*));
}
如果参数可以有多个标记树呢?例如:
assert_eq!(tuplify!(1 + 6, (2, 3), 4), ((7,), (2, 3), (4,)));
然后我们只需要接受一系列标记树,对吗
macro_rules! tuplify {
(@inner ($($args:expr),*)) => (($($args,)*));
(@inner $arg:expr) => (($arg,));
($($($arg_tt:tt)+),*) => (($(tuplify!(@inner $($arg)+),)*));
}
不,那太容易了:
<anon>:12:30: 12:31 error: local ambiguity: multiple parsing options: built-in NTs tt ('arg_tt') or 1 other option.
<anon>:12 assert_eq!(tuplify!(1 + 6, (2, 3), 4), ((7,), (2, 3), (4,)));
我第二次看到
@internal
和@parse
的时候,我需要去跑步。我只是在遵循以下规则。:)
macro_rules! tuplify {
(@as_expr $e:expr) => { $e };
// No more tokens
(@parse { } -> { $($current:tt)* } -> { $($output:tt)* }) => {
tuplify!(@as_expr ( $($output)* ($($current)*,), ))
};
// Comma
(@parse { , $($ts:tt)* } -> { $($current:tt)* } -> { $($output:tt)* }) => {
tuplify!(@parse { $($ts)* } -> { } -> { $($output)* ($($current)*,), })
};
// Tuple followed by a comma, nothing in the current argument yet
(@parse { ($($tuple_item:expr),*) , $($ts:tt)* } -> { } -> { $($output:tt)* }) => {
tuplify!(@parse { $($ts)* } -> { } -> { $($output)* ($($tuple_item,)*), })
};
// Tuple followed by nothing else, nothing in the current argument yet
(@parse { ($($tuple_item:expr),*) } -> { } -> { $($output:tt)* }) => {
tuplify!(@parse { } -> { } -> { $($output)* ($($tuple_item,)*), })
};
// Base case
(@parse { $t:tt $($ts:tt)* } -> { $($current:tt)* } -> { $($output:tt)* }) => {
tuplify!(@parse { $($ts)* } -> { $t $($current)* } -> { $($output)* })
};
// Entry point
($($tokens:tt)*) => (tuplify!(@parse { $($tokens)* } -> { } -> { }));
}
fn main() {
assert_eq!(tuplify!(1 + 6, (2, 3), 4), ((7,), (2, 3), (4,)));
}