英文:
How to use & and | signs in macro_rules pattern
问题
我正在尝试编写一个类似这样的简单宏,以便于编写我的代码:
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)
};
}
然而,我无法在模式中的 expr
后面放置 &
或 |
。我尝试使用 tt
,但它不起作用,因为我不总是只在 $value
中放置一个标记。pat_param
似乎也不能与 &
一起使用。唯一看起来有效的选项是使用 (($value_1:expr) & ($value_2:expr))
,但如果可以不使用额外的括号,那会更好。是否有办法做到这一点?
英文:
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?
答案1
得分: 2
&
不允许用于避免歧义,在声明宏中,expr
参数后面直接使用 &
是无法实现的。
expr
和stmt
只能后跟以下之一:=>
,,
,或;
。
英文:
&
isn't allowed to avoid ambiguity, there is no way to have &
as a token directly after an expr
parameter in a declarative macro.
> expr
and stmt
may only be followed by one of: =>
, ,
, or ;
.
答案2
得分: 1
如果您只想允许单个变量,可选地跟有方法调用,您可以使用以下宏(请注意它不处理通用方法调用语法):
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)
};
}
这个宏并不完美,有一些边界情况,但它应该足够好。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论