简体   繁体   中英

How to parse type in rust macro

I want to write macro, that convert this:

tag_def!("tagname", (isize, String))

Into this:

TagDefinition::new("tagname", ParamGroup(vec![
    TagParam::Int(0),
    TagParam::String(String::new())
]))

I tried to find some way to do that with macro but found nothing. usual macro can't parse type, procedural requires struct to parse. Is the non-over-complicated way exists?

TagParam is a enum:

pub enum TagParam {
    Int(isize),
    String(String),
    Color(Color),
    Tag(Tag),
    Float(f64),
    ParamGroup(Vec<TagParam>)
}

One way you can make this simpler is if all of the values stored in the enum implement Default , the macro can provide Default::default() as the value. My suggestion would be to take this approach. (All of the enum payloads in your example implement Default , with the possible exception of Tag and Color -- I don't know what those types are, but they might implement Default .)

Then, you just need a way to map an identifier (the type name) to an enum variant name, which we can do with another macro:

macro_rules! tag_def_type_variant {
    ( isize ) => { TagParam::Int };
    ( f64 ) => { TagParam::Float };
    // Everything else passes through as-is.
    ( $e:ident ) => { TagParam::$e };
}

Now we can build tag_def in terms of this macro:

macro_rules! tag_def {
    ( $name:literal , ( $( $ty:ident ),+ ) ) => {
        TagDefinition::new($name, TagParam::ParamGroup(vec![
            $(tag_def_type_variant!($ty)(Default::default())),+
        ]))
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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