88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use ast;
11+ use { ast, attr } ;
1212use ext:: tt:: macro_parser;
13+ use feature_gate:: { self , emit_feature_err, Features , GateIssue } ;
1314use parse:: { token, ParseSess } ;
1415use print:: pprust;
1516use symbol:: keywords;
1617use syntax_pos:: { BytePos , Span , DUMMY_SP } ;
1718use tokenstream;
1819
20+ use std:: cell:: RefCell ;
1921use std:: iter:: Peekable ;
2022use std:: rc:: Rc ;
2123
@@ -179,6 +181,8 @@ pub fn parse(
179181 input : tokenstream:: TokenStream ,
180182 expect_matchers : bool ,
181183 sess : & ParseSess ,
184+ features : & RefCell < Features > ,
185+ attrs : & [ ast:: Attribute ] ,
182186) -> Vec < TokenTree > {
183187 // Will contain the final collection of `self::TokenTree`
184188 let mut result = Vec :: new ( ) ;
@@ -187,10 +191,9 @@ pub fn parse(
187191 // additional trees if need be.
188192 let mut trees = input. trees ( ) . peekable ( ) ;
189193 while let Some ( tree) = trees. next ( ) {
190- let tree = parse_tree ( tree, & mut trees, expect_matchers, sess) ;
191-
192194 // Given the parsed tree, if there is a metavar and we are expecting matchers, actually
193195 // parse out the matcher (i.e. in `$id:ident` this would parse the `:` and `ident`).
196+ let tree = parse_tree ( tree, & mut trees, expect_matchers, sess, features, attrs) ;
194197 match tree {
195198 TokenTree :: MetaVar ( start_sp, ident) if expect_matchers => {
196199 let span = match trees. next ( ) {
@@ -244,6 +247,8 @@ fn parse_tree<I>(
244247 trees : & mut Peekable < I > ,
245248 expect_matchers : bool ,
246249 sess : & ParseSess ,
250+ features : & RefCell < Features > ,
251+ attrs : & [ ast:: Attribute ] ,
247252) -> TokenTree
248253where
249254 I : Iterator < Item = tokenstream:: TokenTree > ,
@@ -262,9 +267,9 @@ where
262267 sess. span_diagnostic . span_err ( span, & msg) ;
263268 }
264269 // Parse the contents of the sequence itself
265- let sequence = parse ( delimited. tts . into ( ) , expect_matchers, sess) ;
270+ let sequence = parse ( delimited. tts . into ( ) , expect_matchers, sess, features , attrs ) ;
266271 // Get the Kleene operator and optional separator
267- let ( separator, op) = parse_sep_and_kleene_op ( trees, span, sess) ;
272+ let ( separator, op) = parse_sep_and_kleene_op ( trees, span, sess, features , attrs ) ;
268273 // Count the number of captured "names" (i.e. named metavars)
269274 let name_captures = macro_parser:: count_names ( & sequence) ;
270275 TokenTree :: Sequence (
@@ -317,7 +322,7 @@ where
317322 span,
318323 Rc :: new ( Delimited {
319324 delim : delimited. delim ,
320- tts : parse ( delimited. tts . into ( ) , expect_matchers, sess) ,
325+ tts : parse ( delimited. tts . into ( ) , expect_matchers, sess, features , attrs ) ,
321326 } ) ,
322327 ) ,
323328 }
@@ -373,6 +378,8 @@ fn parse_sep_and_kleene_op<I>(
373378 input : & mut Peekable < I > ,
374379 span : Span ,
375380 sess : & ParseSess ,
381+ features : & RefCell < Features > ,
382+ attrs : & [ ast:: Attribute ] ,
376383) -> ( Option < token:: Token > , KleeneOp )
377384where
378385 I : Iterator < Item = tokenstream:: TokenTree > ,
@@ -401,6 +408,21 @@ where
401408 // (N.B. We need to advance the input iterator.)
402409 match parse_kleene_op ( input, span) {
403410 // #2 is a KleeneOp (this is the only valid option) :)
411+ Ok ( Ok ( op) ) if op == KleeneOp :: ZeroOrOne => {
412+ if !features. borrow ( ) . macro_at_most_once_rep
413+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
414+ {
415+ let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
416+ emit_feature_err (
417+ sess,
418+ "macro_at_most_once_rep" ,
419+ span,
420+ GateIssue :: Language ,
421+ explain,
422+ ) ;
423+ }
424+ return ( Some ( token:: Question ) , op) ;
425+ }
404426 Ok ( Ok ( op) ) => return ( Some ( token:: Question ) , op) ,
405427
406428 // #2 is a random token (this is an error) :(
@@ -410,6 +432,19 @@ where
410432 Err ( span) => span,
411433 }
412434 } else {
435+ if !features. borrow ( ) . macro_at_most_once_rep
436+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
437+ {
438+ let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
439+ emit_feature_err (
440+ sess,
441+ "macro_at_most_once_rep" ,
442+ span,
443+ GateIssue :: Language ,
444+ explain,
445+ ) ;
446+ }
447+
413448 // #2 is a random tree and #1 is KleeneOp::ZeroOrOne
414449 return ( None , op) ;
415450 }
@@ -418,6 +453,21 @@ where
418453 // #1 is a separator followed by #2, a KleeneOp
419454 Ok ( Err ( ( tok, span) ) ) => match parse_kleene_op ( input, span) {
420455 // #2 is a KleeneOp :D
456+ Ok ( Ok ( op) ) if op == KleeneOp :: ZeroOrOne => {
457+ if !features. borrow ( ) . macro_at_most_once_rep
458+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
459+ {
460+ let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
461+ emit_feature_err (
462+ sess,
463+ "macro_at_most_once_rep" ,
464+ span,
465+ GateIssue :: Language ,
466+ explain,
467+ ) ;
468+ }
469+ return ( Some ( tok) , op) ;
470+ }
421471 Ok ( Ok ( op) ) => return ( Some ( tok) , op) ,
422472
423473 // #2 is a random token :(
@@ -431,7 +481,13 @@ where
431481 Err ( span) => span,
432482 } ;
433483
434- sess. span_diagnostic
435- . span_err ( span, "expected one of: `*`, `+`, or `?`" ) ;
484+ if !features. borrow ( ) . macro_at_most_once_rep
485+ && !attr:: contains_name ( attrs, "allow_internal_unstable" )
486+ {
487+ sess. span_diagnostic
488+ . span_err ( span, "expected one of: `*`, `+`, or `?`" ) ;
489+ } else {
490+ sess. span_diagnostic . span_err ( span, "expected `*` or `+`" ) ;
491+ }
436492 ( None , KleeneOp :: ZeroOrMore )
437493}
0 commit comments