How to use a colon as a literal in a macro rule?

I'm learning macros and experimenting with mimicing to a small degree the Objective-C syntax, but I can't seem to get a pattern rule to work with a colon as a literal. The goal is to use a syntax like this:

envar![setValue: "/home/me" forKey: "HOME"];

yet, if my rule is such:

(setValue: $value:expr; forKey: $key:expr) => {
    println!("setValue:{} forKey:{}", $value, $key);
}

I get the following error:

error: expected type, found `"/home/me"`
--> src/fs.rs:72:26
|
72 |         envar![setValue: "/home/me" forKey: "HOME"];
|                             ^^^^^^^^^^ expecting a type here because of type ascription

Is there a way to escape the colon?

Aren't you missing a semicolon after "/home/me" in the macro invocation?

Yup, by design. I don't want a semicolon in the macro invocation. So why do I have one in the rule? It tells me I need one after a expr.

Ok, but what you wrote requires a semicolon :slight_smile:.

An expr type has limited number of separator tokens that can follow it, and whitespace isn't one of them AFAIK. One way to achieve the above is to use the tt (token tree) type:

(setValue: $value:tt  forKey: $key:tt) => {
       println!("setValue:{} forKey:{}", $value, $key);
}

I don't know if this is the best or even correct approach (I'm not a macros expert) but it does work because tt's can be followed by anything.

I know :slight_smile:

Did you run your code? Unfortunately it still complains that "home/me" should be a type because of type ascription: the colon following setValue.

I ran:

macro_rules! envar {
    (setValue: $value:tt forKey: $key:tt) => {
       println!("setValue:{} forKey:{}", $value, $key);
    }
}

fn main() {
    envar![setValue: "/home/me" forKey: "HOME"];
}

Playground

Maybe you can put up a playground that shows exactly the error you're getting and what you're trying to do.

I found the problem. I had another rule above it (that I didn't post here for berevity sake) that was the one complaining. It's a ($key:expr) match so it was getting confused with the setValue: forKey: syntax.

Thanks for your help! :smiley: