繁体   English   中英

将宏 arguments 传递给其他宏

[英]pass macro arguments to other macro

我是 rust 的新手。 我正在尝试创建一个宏,它需要一个缓冲区,然后从中解码一些数据并创建变量的给定列表。 如果发生错误,那么它应该打印错误并继续,因为我将在接收缓冲区的循环中调用它。 像这样的东西: -

for bin_ref in bufs {

   extract!( bin_ref anime &str episodes u32 season u32);

   //if everything goes ok then do some cool stuff with
   //above variables otherwise take next buf_ref    
}

我怎样才能做到这一点? 因此,我采用了这种方法:-

#[macro_export]
macro_rules! extract {

    ( $buf:ident $($var:ident $typ:ty),* ) => {
        $(
            ext_type!( $buf $var $typ );
        )*
    };
}

#[macro_export]
macro_rules! ext_type {
    ( $buf:ident $var:ident &str ) => {

        let mut $var : &str = ""; //some string specific function
        println!("doing cool things with '{}' which is string ",$var);        

    };
    ( $buf:ident $var:ident u32 ) => {
        let mut $var : u32 = 34; //some u32 specific function
        println!("doing cool things with '{}' which is u32",$var);
    }
}

我有以下测试 function:-

fn macro_test() {

    let mut bin_ref : &[u8] = &[0u8;100];

    ext_type!(bin_ref anime &str); // works
    ext_type!(bin_ref episodes u32 ); // works

    extract!( bin_ref username &str, password &str ); // does not work. why ??
}

当我编译这个时,我得到以下错误: -

error: no rules expected the token `&str`
  --> src/easycode.rs:11:34
   |
11 |             ext_type!( $buf $var $typ );
   |                                  ^^^^ no rules expected this token in macro call
...
19 | macro_rules! ext_type {
   | --------------------- when calling this macro
...
48 |     extract!( bin_ref username &str, password &str );
   |     ------------------------------------------------- in this macro invocation

为什么我不能只将$typ传递给ext_type! 宏? 从代码调用时它可以工作

ext_type! 宏的规则最后需要文字标记&stru32 这些文字标记无法匹配extract!中的匹配片段$typ:ty . 为了成功地将文字标记与匹配的片段匹配, 它必须是ttidentlifetime

在这种情况下,唯一可行的选项是tt ,简单地说,就是一个解析器令牌。 但是,一种类型通常由多个标记组成; &str ,它由两个标记&str组成。 因此,我们必须使用重复来完全捕获具有tt s 的类型: $($typ:tt)+会做得很好。

然而,对tt使用无限重复是有代价的——一个tt将匹配几乎所有内容,所以简单地将$typ:ty替换为$($typ:tt)+是行不通的,因为$typ重复将捕获所有内容,直到在宏调用结束时,为了防止这种情况发生,我们必须在宏规则匹配器中划定类型标记树,以阻止它消耗所有内容。 以使调用稍微冗长为代价,将括号中的重复括起来将为我们提供很好的服务,并停止与我们想要的完全匹配的令牌树。 修改后的宏如下所示:

#[macro_export]
macro_rules! extract {
    ( $buf:ident $($var:ident ($($typ:tt)+)),* ) => {
        $(
            ext_type!( $buf $var $($typ)+);
        )*
    };
}

注意匹配器中的$typ:ty替换为($($typ:tt)+) (这是一个用括号括起来的标记树重复),以及转录器中的$typ替换为$($typ)+ .

宏规则调用如下:

extract!(bin_ref username (&str), password (&str), id (u32));

Rust游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM