Reputation: 73
I'm trying to write a simple macro like this, to facilitate the writing of my code
enum Term {
Or(Box<Term>, Box<Term>),
And(Box<Term>, Box<Term>),
Value(u8),
}
macro_rules! term {
($value_1:expr & $value_2:expr) => {
Term::And(Box::new($value_1), Box::new($value_2))
};
($value_1:expr | $value_2: expr) => {
Term::Or(Box::new($value_1), Box::new($value_2))
};
($value: expr) => {
Term::Value($value)
};
}
However, I cannot put a &
or |
after an expr
in my pattern. I tried using tt
, but it didn't work because I'm not always just putting one token in my $value
. pat_param
doesn't seem to work with &
either.
The only option that seems to work would be to use (($value_1:expr) & ($value_2:expr))
, but if I could do without the extra parentheses, it'd be better.
Is there a way to do this?
Upvotes: 0
Views: 286
Reputation: 71025
If you only want to allow a single variable, optionally with a method call after, you can use the following macro (note it does not handle generic method call syntax):
macro_rules! term {
(
$name:ident $( .$method:ident( $($argument:expr),* $(,)? ) )?
$($rest:tt)+
) => {
term!(@parsed_lhs
( $name $( .$method( $($argument),* ) )? )
$($rest)*
)
};
(@parsed_lhs $value_1:tt & $value_2:expr) => {
Term::And(Box::new($value_1), Box::new($value_2))
};
(@parsed_lhs $value_1:tt | $value_2:expr) => {
Term::Or(Box::new($value_1), Box::new($value_2))
};
($value:expr) => {
Term::Value($value)
};
}
This macro is not perfect, it has some edge cases, but it should be good enough.
Upvotes: 1