8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use ast;
11
+ use { ast, attr } ;
12
12
use ext:: tt:: macro_parser;
13
+ use feature_gate:: { self , emit_feature_err, Features , GateIssue } ;
13
14
use parse:: { token, ParseSess } ;
14
15
use print:: pprust;
15
16
use symbol:: keywords;
16
17
use syntax_pos:: { BytePos , Span , DUMMY_SP } ;
17
18
use tokenstream;
18
19
20
+ use std:: cell:: RefCell ;
19
21
use std:: iter:: Peekable ;
20
22
use std:: rc:: Rc ;
21
23
@@ -179,6 +181,8 @@ pub fn parse(
179
181
input : tokenstream:: TokenStream ,
180
182
expect_matchers : bool ,
181
183
sess : & ParseSess ,
184
+ features : & RefCell < Features > ,
185
+ attrs : & [ ast:: Attribute ] ,
182
186
) -> Vec < TokenTree > {
183
187
// Will contain the final collection of `self::TokenTree`
184
188
let mut result = Vec :: new ( ) ;
@@ -187,10 +191,9 @@ pub fn parse(
187
191
// additional trees if need be.
188
192
let mut trees = input. trees ( ) . peekable ( ) ;
189
193
while let Some ( tree) = trees. next ( ) {
190
- let tree = parse_tree ( tree, & mut trees, expect_matchers, sess) ;
191
-
192
194
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
193
195
// 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) ;
194
197
match tree {
195
198
TokenTree :: MetaVar ( start_sp, ident) if expect_matchers => {
196
199
let span = match trees. next ( ) {
@@ -244,6 +247,8 @@ fn parse_tree<I>(
244
247
trees : & mut Peekable < I > ,
245
248
expect_matchers : bool ,
246
249
sess : & ParseSess ,
250
+ features : & RefCell < Features > ,
251
+ attrs : & [ ast:: Attribute ] ,
247
252
) -> TokenTree
248
253
where
249
254
I : Iterator < Item = tokenstream:: TokenTree > ,
@@ -262,9 +267,9 @@ where
262
267
sess. span_diagnostic . span_err ( span, & msg) ;
263
268
}
264
269
// 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 ) ;
266
271
// 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 ) ;
268
273
// Count the number of captured "names" (i.e. named metavars)
269
274
let name_captures = macro_parser:: count_names ( & sequence) ;
270
275
TokenTree :: Sequence (
@@ -317,7 +322,7 @@ where
317
322
span,
318
323
Rc :: new ( Delimited {
319
324
delim : delimited. delim ,
320
- tts : parse ( delimited. tts . into ( ) , expect_matchers, sess) ,
325
+ tts : parse ( delimited. tts . into ( ) , expect_matchers, sess, features , attrs ) ,
321
326
} ) ,
322
327
) ,
323
328
}
@@ -373,6 +378,8 @@ fn parse_sep_and_kleene_op<I>(
373
378
input : & mut Peekable < I > ,
374
379
span : Span ,
375
380
sess : & ParseSess ,
381
+ features : & RefCell < Features > ,
382
+ attrs : & [ ast:: Attribute ] ,
376
383
) -> ( Option < token:: Token > , KleeneOp )
377
384
where
378
385
I : Iterator < Item = tokenstream:: TokenTree > ,
@@ -401,6 +408,21 @@ where
401
408
// (N.B. We need to advance the input iterator.)
402
409
match parse_kleene_op ( input, span) {
403
410
// #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
+ }
404
426
Ok ( Ok ( op) ) => return ( Some ( token:: Question ) , op) ,
405
427
406
428
// #2 is a random token (this is an error) :(
@@ -410,6 +432,19 @@ where
410
432
Err ( span) => span,
411
433
}
412
434
} 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
+
413
448
// #2 is a random tree and #1 is KleeneOp::ZeroOrOne
414
449
return ( None , op) ;
415
450
}
@@ -418,6 +453,21 @@ where
418
453
// #1 is a separator followed by #2, a KleeneOp
419
454
Ok ( Err ( ( tok, span) ) ) => match parse_kleene_op ( input, span) {
420
455
// #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
+ }
421
471
Ok ( Ok ( op) ) => return ( Some ( tok) , op) ,
422
472
423
473
// #2 is a random token :(
@@ -431,7 +481,13 @@ where
431
481
Err ( span) => span,
432
482
} ;
433
483
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
+ }
436
492
( None , KleeneOp :: ZeroOrMore )
437
493
}
0 commit comments