“This is the 21st day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”
Macros currently don’t allow matching literal meanings, and expr doesn’t work for us because it might accidentally match things like 2+3… Such a sequence, rather than just taking a number, so we will resort to TT – a generic marker matcher.
It matches only a tag tree (either as a literal/identifier/lifetime/etc so that the original markup or more tags () / [] {}).
macro_rules! rpn {
($num:tt) => {
// TODO
};
}
Copy the code
Now, we need a variable for the stack.
Macros cannot use real variables because we want the stack to exist only at compile time. So, instead, there is a separate sequence of tags that can be passed and therefore used as a kind of accumulator.
In our case, let’s represent it as a comma-separated sequence of EXPR (because we’re going to use it not only for simple numbers, but also for infix expressions in the middle) and wrap it in parentheses, separate from the rest of the input.
macro_rules! rpn {
([ $($stack:expr),* ] $num:tt) => {
// TODO
};
}
Copy the code
Now, a tag sequence isn’t really a variable — you can’t modify it in place and then do something about it.
Instead, you can create a new copy of the tag sequence with the necessary modifications and recursively call the same macro again.
If you have a background in functional languages, or have ever used any library that provides immutable data, there are two ways to change the data: by creating a modified copy and using a recursive processing list.
macro_rules!rpn { ([ $($stack:expr),* ] $num:tt) => { rpn! ([ $num $(, $stack)* ]) }; }Copy the code
Now, obviously, there is only one number is quite impossible, is not very practical for us, so we need to put the number of matches any of the other things into a string of zero or more tt tags, the tags can be passed on to our next call macros, matching and for further processing.
macro_rules!rpn { ([ $($stack:expr),* ] $num:tt $($rest:tt)*) => { rpn! ([ $num $(, $stack)* ] $($rest)*) }; }Copy the code