Rust macro_rules вложенное повторение - PullRequest
1 голос
/ 05 апреля 2020

В макро_рулес! транскрибер, вложенные повторы не обрабатываются должным образом. Это прекрасно работает:

macro_rules! demo_macro {
    ($op:tt; $($arg:tt),*) {
        ($($op * $arg),*)
    }
}

fn main() {
    println!("{?:}", demo_macro!(2; 1,2,3));
}

и выводит (2, 4, 6), но это не компилируется:

macro_rules! demo_macro {
    ([$($op:tt)*] $($arg:tt),*) {
        ($($($op)* $arg),*)
    }
}

fn main() {
    println!("{?:}", demo_macro!([2*] 1,2,3));
}

и приводит к этому сообщению об ошибке:

error: meta-variable `op` repeats 2 times, but `arg` repeats 3 times
 --> src/main.rs:3:11
  |
3 |         ($($($op)* $arg),*)
  |           ^^^^^^^^^^^^^^

Если я изменю 1,2,3 на 1,2, чтобы количество повторений совпадало, я получаю это сообщение об ошибке:

error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 --> src/main.rs:3:13
  |
3 |         ($($($op)* $arg),*)
  |             ^^^^^

Любая идея, как сделать demo_macro!([2*] 1,2,3) результатом в (2, 4, 6)?

1 Ответ

0 голосов
/ 05 апреля 2020

Да, это работает!

macro_rules! unbracket {
    (_ [$($tt1:tt)*]) => { $($tt1)* };
    (() [$($tt1:tt)*]) => { ($($tt1)*) };
    ([] [$($tt1:tt)*]) => { [$($tt1)*] };
    ({} [$($tt1:tt)*]) => { {$($tt1)*} };
    ($tt0:tt [$($tt1:tt)*] @unbracket ($($tt2:tt)*) $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
    ($tt0:tt [$($tt1:tt)*] @unbracket [$($tt2:tt)*] $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
    ($tt0:tt [$($tt1:tt)*] @unbracket {$($tt2:tt)*} $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
    ($tt0:tt [$($tt1:tt)*] $tt2:tt $($tt3:tt)*) => { unbracket!{$tt0 [$($tt1)* $tt2] $($tt3)*} };
}

macro_rules! demo_macro {
    ($op:tt $($arg:tt),*) => {
        unbracket!(() [] $(@unbracket $op $arg),*)
    }
}

fn main() {
    println!("{:?}", demo_macro!([2*] 1,2,3));
}
...