Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can I specify an operator or other syntactic literal within a macro input?

First, I know this is not a good use of macros but I’m learning what I can do.

I have a struct Rational:

pub struct Rational{
    pub n: i128,
    pub d : i128
}

I have a macro that builds these:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

macro_rules! rat{
    ($n : expr,  $d : expr) => {
        Rational{n : $n,d:  $d}
    }
}

The syntax for calling that macro looks like : rat!(1, 3). I would like it to visually show a fractional format, so you would call it like rat!(1 / 3) instead, and the macro would parse that expression to yield the same result. (Note that if it first evaluates 1/3, even as a float type, it will not exactly correspond as 1/3 does not correspond exactly to any float.)

I’m hoping there’s some syntax like:

macro_rules! rat{
    ($n : expr `/` $d : expr) => {
        Rational{n : $n,d:  $d}
    }
}

where I can specify syntax to be used in the call. (That attempt does not compile, of course.)

Again, obviously this is silly and an X/Y problem and all that. For context, I’m considering building an equation wrangling system, and at some point I’d like to be able to parse things from a math-y syntax, which might actually justify the use of macros. This is just a baby step.

Does such a thing exist using declarative macros?
If not, is it possible with procedural macros?
Finally, I know that in Scala macros there would be no way to make that work for literal values, because the expression 1/3 would be resolved so early in the compilation process the AST would be gone by the time even macros are called. Is that also the case in Rust?

>Solution :

Yes, you can use the / token directly in the rule:

#[derive(Debug)]
struct Rational{
    n: i128,
    d: i128
}

macro_rules! rat {
    ($n:literal / $d:literal) => {
        Rational { n: $n, d: $d }
    };
}

fn main() {
    println!("rat!(1 / 3) = {:?}", rat!(1 / 3));
}
rat!(1 / 3) = Rational { n: 1, d: 3 }

However, notice I have changed the arguments from expr to literal. Your question seems to imply this is fine for your use-case, but I bring it up because at least the first parameter $n cannot be an expr. It would cause a parsing ambiguity because / is a valid continuation of an expression and Rust simply doesn’t allow / as a separator after a expr.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading