【问题标题】:How do I write macro arguments which capture parenthesis?如何编写捕获括号的宏参数?
【发布时间】:2018-03-28 05:09:35
【问题描述】:

我希望编写一个 Rust 宏,它将其整个参数转发给第二个宏——即使该参数包含令人兴奋的括号。

这是我迄今为止尝试过的:

macro_rules! parse {
    (done) => (println!("done!"));
    (if ($cond:tt) {$then:tt}) => (println!("if! "); parse!($cond); parse($then));
}

macro_rules! forward {
    ($($e:tt)*) => (parse!($($e)*; done));
}

fn main() {
    forward!(if (done) {done} );
}

这不起作用,并产生错误:

error: no rules expected the token `if`

我在这里做错了什么?

编辑:除了简单地将参数转发给forward,我还希望将标记; done“粘贴”到forward 参数的末尾。有没有办法在保持这种行为的同时完成这项工作?

【问题讨论】:

    标签: macros rust


    【解决方案1】:

    问题是forward 中的; done。这里发生的是宏扩展代码一次将文字输入标记与武器匹配。如果一只手臂不匹配,它会放弃并尝试下一只手臂。当它用尽全力尝试时,它必须失败并解释原因。

    但是输入中的哪个标记是问题?回答当可能涉及多个手臂时很难,所以它只是选择第一个标记并说“这是问题所在”。

    每当您看到宏扩展抱怨输入中的第一个标记不匹配时,很可能是输入中的某些内容导致它出错。

    修复该问题(并修复缺少 !parse 调用)给出:

    macro_rules! parse {
        (done) => (println!("done!"));
        (if ($cond:tt) {$then:tt}) => (println!("if! "); parse!($cond); parse!($then));
    }
    
    macro_rules! forward {
        ($($e:tt)*) => (parse!($($e)*));
    }
    
    fn main() {
        forward!(if (done) {done} );
    }
    

    【讨论】:

    • 实际上,我希望将标记“粘贴”; done 到转发的输入;这就是他们在那里的目的。这可能吗?
    • @MatthewMilano 我不明白您所说的“粘贴”是什么意思。您添加了令牌就好了,但没有处理它们的规则。这就像将两个参数传递给一个只需要一个参数的函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    相关资源
    最近更新 更多