// be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to
// find out which.
Ok(Ok(op)) => {
+ assert_eq!(op, KleeneOp::ZeroOrOne);
+
// Lookahead at #2. If it is a KleenOp, then #1 is a separator.
let is_1_sep = if let Some(&tokenstream::TokenTree::Token(_, ref tok2)) = input.peek() {
kleene_op(tok2).is_some()
#![allow(unused_macros)]
macro_rules! assign {
- (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR 14:22: 14:29: expected one of: `*`, `+`, or `?`
+ (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
$($a)* = $($b)*
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`.
+// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the
+// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to
+// exercise that logic in the macro parser.
+//
+// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but
+// included for consistency with `+` and `*`.
+//
+// This test focuses on error cases.
+
#![feature(macro_at_most_once_rep)]
macro_rules! foo {
($(a),?) => {} // comma separator is meaningless for `?`
}
-macro_rules! bar {
+macro_rules! barplus {
($(a)?+) => {}
}
+macro_rules! barstar {
+ ($(a)?*) => {}
+}
+
pub fn main() {
foo!(a?a?a); //~ ERROR no rules expected the token `?`
foo!(a?a); //~ ERROR no rules expected the token `?`
baz!(a?a?a,); //~ ERROR no rules expected the token `?`
baz!(a?a,); //~ ERROR no rules expected the token `?`
baz!(a?,); //~ ERROR no rules expected the token `?`
- bar!(); //~ ERROR unexpected end of macro invocation
- bar!(a?); //~ ERROR unexpected end of macro invocation
+ barplus!(); //~ ERROR unexpected end of macro invocation
+ barplus!(a?); //~ ERROR unexpected end of macro invocation
+ barstar!(a?); //~ ERROR unexpected end of macro invocation
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`.
+// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the
+// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to
+// exercise that logic in the macro parser.
+//
+// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but
+// included for consistency with `+` and `*`.
+//
+// This test focuses on non-error cases and making sure the correct number of repetitions happen.
+
#![feature(macro_at_most_once_rep)]
macro_rules! foo {
- ($(a)?) => {}
+ ($($a:ident)? ; $num:expr) => { {
+ let mut x = 0;
+
+ $(
+ x += $a;
+ )?
+
+ assert_eq!(x, $num);
+ } }
}
macro_rules! baz {
- ($(a),?) => {} // comma separator is meaningless for `?`
+ ($($a:ident),? ; $num:expr) => { { // comma separator is meaningless for `?`
+ let mut x = 0;
+
+ $(
+ x += $a;
+ )?
+
+ assert_eq!(x, $num);
+ } }
}
-macro_rules! bar {
- ($(a)?+) => {}
+macro_rules! barplus {
+ ($($a:ident)?+ ; $num:expr) => { {
+ let mut x = 0;
+
+ $(
+ x += $a;
+ )+
+
+ assert_eq!(x, $num);
+ } }
+}
+
+macro_rules! barstar {
+ ($($a:ident)?* ; $num:expr) => { {
+ let mut x = 0;
+
+ $(
+ x += $a;
+ )*
+
+ assert_eq!(x, $num);
+ } }
}
pub fn main() {
- foo!();
- foo!(a);
- baz!();
- baz!(a);
- bar!(a);
- bar!(a?a);
- bar!(a?a?a);
+ let a = 1;
+
+ // accept 0 or 1 repetitions
+ foo!( ; 0);
+ foo!(a ; 1);
+ baz!( ; 0);
+ baz!(a ; 1);
+
+ // Make sure using ? as a separator works as before
+ barplus!(a ; 1);
+ barplus!(a?a ; 2);
+ barplus!(a?a?a ; 3);
+ barstar!( ; 0);
+ barstar!(a ; 1);
+ barstar!(a?a ; 2);
+ barstar!(a?a?a ; 3);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt
-// feature gate is not used.
+// Test that `?` macro Kleene operator can not be used when the `macro_at_most_once_rep` feature
+// gate is not used.
macro_rules! m { ($(a)?) => {} }
//~^ ERROR Using the `?` macro Kleene operator for "at most one" repetition is unstable