eadren
August 29, 2021, 6:53am
1
How to match a optional repetition character(eg. '?' ) in input using macro?
macro_rules! g4 {
($rule:ident: $($sub_rule:ident$(?)?) +) => {
$(
print!("{}", $sub_rule);
$(print!("optional??");)?
)+
};
}
fn main() {
let s = "MyRule";
let s1 = "s1";
let s2 = "s2";
g4!(s: s1? s2);
I want to expand g4!(s: s1? s2) => {
print!("{}", s1);
print!("optional??");
print!("{}", s2);
}
complier compliant that:
error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
--> src/main.rs:4:37
|
4 | $(print!("{}", $sub_rule); $(print!("optional??");)?)+
|
1 Like
ayosec
August 29, 2021, 1:26pm
2
A possible solution is to add an extra pattern for ident?
.
macro_rules! g4 {
($rule:ident: $sub_rule:ident ? $($tt:tt)*) => {
println!("optional {}", $sub_rule);
g4!($rule: $($tt)*);
};
($rule:ident: $sub_rule:ident $($tt:tt)*) => {
println!("{}", $sub_rule);
g4!($rule: $($tt)*);
};
($rule:ident:) => {};
}
fn main() {
let s = "MyRule";
let s1 = "A";
let s2 = "B";
let s3 = "C";
let s4 = "D";
g4!(s: s1 s2? s3? s4);
}
Output:
A
optional B
optional C
D
1 Like
eadren
August 30, 2021, 2:33am
3
I change the macro_rule a little, but it cannot work.
macro_rules! g4 {
($rule:ident: $($tt:tt)*) => {
print!("{}: ", $rule);
g4!($($tt)*);
};
// ($rule:ident: $sub_rule:tt $($tt:tt)*) => {
// print!("{}", $sub_rule);
// g4!($($tt)*);
// };
($sub_rule:tt $($tt:tt)*) => {
print!("{}", $sub_rule);
g4!($($tt)*);
};
($sub_rule:tt ? $($tt:tt)*) => {
print!("({})?", $sub_rule);
g4!($($tt)*);
};
() => {};
}
fn main() {
let s = "MyRule";
let s1 = "s1";
let s2 = "s2";
let s3 = "s3";
g4!(s: s1 s2? s3 s1 s2);
}
error: expected expression, found `?`
--> src/main.rs:35:17
|
35 | g4!(s: s1 s2? s3 s1 s2);
| ^ expected expression
the order of pattern arms in macros matters; try putting the one with the ?
before the one without it.
I believe your second rule is matching, so it's passing the ?
into the println!
3 Likes
Another option is to use a dummy metavariable:
macro_rules! g4 {
($rule:ident: $($sub_rule:ident$(? $([$($_:tt)* $optional:tt])?)?) +) => {
$(
print!("{}", $sub_rule);
$($($optional)?; print!("optional??");)?
)+
};
}
fn main() {
let s = "MyRule";
let s1 = "s1";
let s2 = "s2";
g4!(s: s1? s2);
}
The $optional
metavar will never be matched, but it allows you to give a name to the optional part of the input.
system
Closed
November 28, 2021, 7:57am
7
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.