@@ -386,26 +386,72 @@ where
386386{
387387 // We basically look at two token trees here, denoted as #1 and #2 below
388388 let span = match parse_kleene_op ( input, span) {
389- // #1 is any KleeneOp (`?`)
390- Ok ( Ok ( op) ) if op == KleeneOp :: ZeroOrOne => {
391- if !features. macro_at_most_once_rep
392- && !attr:: contains_name ( attrs, "allow_internal_unstable" )
393- {
394- let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
395- emit_feature_err (
396- sess,
397- "macro_at_most_once_rep" ,
398- span,
399- GateIssue :: Language ,
400- explain,
401- ) ;
389+ // #1 is a `+` or `*` KleeneOp
390+ //
391+ // `?` is ambiguous: it could be a separator or a Kleene::ZeroOrOne, so we need to look
392+ // ahead one more token to be sure.
393+ Ok ( Ok ( op) ) if op != KleeneOp :: ZeroOrOne => return ( None , op) ,
394+
395+ // #1 is `?` token, but it could be a Kleene::ZeroOrOne without a separator or it could
396+ // be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to
397+ // find out which.
398+ Ok ( Ok ( op) ) => {
399+ assert_eq ! ( op, KleeneOp :: ZeroOrOne ) ;
400+
401+ // Lookahead at #2. If it is a KleenOp, then #1 is a separator.
402+ let is_1_sep = if let Some ( & tokenstream:: TokenTree :: Token ( _, ref tok2) ) = input. peek ( ) {
403+ kleene_op ( tok2) . is_some ( )
404+ } else {
405+ false
406+ } ;
407+
408+ if is_1_sep {
409+ // #1 is a separator and #2 should be a KleepeOp::*
410+ // (N.B. We need to advance the input iterator.)
411+ match parse_kleene_op ( input, span) {
412+ // #2 is a KleeneOp (this is the only valid option) :)
413+ Ok ( Ok ( op) ) if op == KleeneOp :: ZeroOrOne => {
414+ if !features. macro_at_most_once_rep
415+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
416+ {
417+ let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
418+ emit_feature_err (
419+ sess,
420+ "macro_at_most_once_rep" ,
421+ span,
422+ GateIssue :: Language ,
423+ explain,
424+ ) ;
425+ }
426+ return ( Some ( token:: Question ) , op) ;
427+ }
428+ Ok ( Ok ( op) ) => return ( Some ( token:: Question ) , op) ,
429+
430+ // #2 is a random token (this is an error) :(
431+ Ok ( Err ( ( _, span) ) ) => span,
432+
433+ // #2 is not even a token at all :(
434+ Err ( span) => span,
435+ }
436+ } else {
437+ if !features. macro_at_most_once_rep
438+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
439+ {
440+ let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
441+ emit_feature_err (
442+ sess,
443+ "macro_at_most_once_rep" ,
444+ span,
445+ GateIssue :: Language ,
446+ explain,
447+ ) ;
448+ }
449+
450+ // #2 is a random tree and #1 is KleeneOp::ZeroOrOne
451+ return ( None , op) ;
402452 }
403- return ( None , op) ;
404453 }
405454
406- // #1 is any KleeneOp (`+`, `*`)
407- Ok ( Ok ( op) ) => return ( None , op) ,
408-
409455 // #1 is a separator followed by #2, a KleeneOp
410456 Ok ( Err ( ( tok, span) ) ) => match parse_kleene_op ( input, span) {
411457 // #2 is a KleeneOp :D
@@ -421,11 +467,8 @@ where
421467 GateIssue :: Language ,
422468 explain,
423469 ) ;
424- } else {
425- sess. span_diagnostic
426- . span_err ( span, "`?` macro repetition does not allow a separator" ) ;
427470 }
428- return ( None , op) ;
471+ return ( Some ( tok ) , op) ;
429472 }
430473 Ok ( Ok ( op) ) => return ( Some ( tok) , op) ,
431474
@@ -440,7 +483,9 @@ where
440483 Err ( span) => span,
441484 } ;
442485
443- if !features. macro_at_most_once_rep && !attr:: contains_name ( attrs, "allow_internal_unstable" ) {
486+ if !features. macro_at_most_once_rep
487+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
488+ {
444489 sess. span_diagnostic
445490 . span_err ( span, "expected one of: `*`, `+`, or `?`" ) ;
446491 } else {
0 commit comments