10
10
11
11
use { ast, attr} ;
12
12
use ext:: tt:: macro_parser;
13
- use feature_gate:: { self , emit_feature_err , Features , GateIssue } ;
13
+ use feature_gate:: Features ;
14
14
use parse:: { token, ParseSess } ;
15
15
use print:: pprust;
16
16
use symbol:: keywords;
17
- use syntax_pos:: { BytePos , Span , DUMMY_SP } ;
17
+ use syntax_pos:: { BytePos , Span , DUMMY_SP , edition :: Edition } ;
18
18
use tokenstream;
19
19
20
20
use std:: iter:: Peekable ;
@@ -184,6 +184,7 @@ pub fn parse(
184
184
sess : & ParseSess ,
185
185
features : & Features ,
186
186
attrs : & [ ast:: Attribute ] ,
187
+ edition : Edition ,
187
188
) -> Vec < TokenTree > {
188
189
// Will contain the final collection of `self::TokenTree`
189
190
let mut result = Vec :: new ( ) ;
@@ -194,7 +195,7 @@ pub fn parse(
194
195
while let Some ( tree) = trees. next ( ) {
195
196
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
196
197
// parse out the matcher (i.e. in `$id:ident` this would parse the `:` and `ident`).
197
- let tree = parse_tree ( tree, & mut trees, expect_matchers, sess, features, attrs) ;
198
+ let tree = parse_tree ( tree, & mut trees, expect_matchers, sess, features, attrs, edition ) ;
198
199
match tree {
199
200
TokenTree :: MetaVar ( start_sp, ident) if expect_matchers => {
200
201
let span = match trees. next ( ) {
@@ -252,6 +253,7 @@ fn parse_tree<I>(
252
253
sess : & ParseSess ,
253
254
features : & Features ,
254
255
attrs : & [ ast:: Attribute ] ,
256
+ edition : Edition ,
255
257
) -> TokenTree
256
258
where
257
259
I : Iterator < Item = tokenstream:: TokenTree > ,
@@ -270,9 +272,23 @@ where
270
272
sess. span_diagnostic . span_err ( span, & msg) ;
271
273
}
272
274
// Parse the contents of the sequence itself
273
- let sequence = parse ( delimited. tts . into ( ) , expect_matchers, sess, features, attrs) ;
275
+ let sequence = parse (
276
+ delimited. tts . into ( ) ,
277
+ expect_matchers,
278
+ sess,
279
+ features,
280
+ attrs,
281
+ edition,
282
+ ) ;
274
283
// Get the Kleene operator and optional separator
275
- let ( separator, op) = parse_sep_and_kleene_op ( trees, span, sess, features, attrs) ;
284
+ let ( separator, op) = parse_sep_and_kleene_op (
285
+ trees,
286
+ span,
287
+ sess,
288
+ features,
289
+ attrs,
290
+ edition
291
+ ) ;
276
292
// Count the number of captured "names" (i.e. named metavars)
277
293
let name_captures = macro_parser:: count_names ( & sequence) ;
278
294
TokenTree :: Sequence (
@@ -322,19 +338,46 @@ where
322
338
span,
323
339
Lrc :: new ( Delimited {
324
340
delim : delimited. delim ,
325
- tts : parse ( delimited. tts . into ( ) , expect_matchers, sess, features, attrs) ,
341
+ tts : parse (
342
+ delimited. tts . into ( ) ,
343
+ expect_matchers,
344
+ sess,
345
+ features,
346
+ attrs,
347
+ edition
348
+ ) ,
326
349
} ) ,
327
350
) ,
328
351
}
329
352
}
330
353
331
354
/// Takes a token and returns `Some(KleeneOp)` if the token is `+` `*` or `?`. Otherwise, return
332
- /// `None`.
333
- fn kleene_op ( token : & token:: Token ) -> Option < KleeneOp > {
355
+ /// `None`. This function takes into account what edition and feature flags are enabled.
356
+ fn kleene_op (
357
+ token : & token:: Token ,
358
+ span : Span ,
359
+ sess : & ParseSess ,
360
+ edition : Edition ,
361
+ features : & Features ,
362
+ attrs : & [ ast:: Attribute ] ,
363
+ ) -> Option < KleeneOp > {
334
364
match * token {
335
365
token:: BinOp ( token:: Star ) => Some ( KleeneOp :: ZeroOrMore ) ,
336
366
token:: BinOp ( token:: Plus ) => Some ( KleeneOp :: OneOrMore ) ,
337
- token:: Question => Some ( KleeneOp :: ZeroOrOne ) ,
367
+ token:: Question =>
368
+ if edition >= Edition :: Edition2018
369
+ || ( features. macro_at_most_once_rep
370
+ && attr:: contains_name ( attrs, "allow_internal_unstable" ) ) {
371
+ Some ( KleeneOp :: ZeroOrOne )
372
+ } else {
373
+ sess. span_diagnostic
374
+ . span_warn (
375
+ span,
376
+ "`?` as a separator is deprecated and \
377
+ will be removed in an upcoming edition."
378
+ ) ;
379
+ None
380
+ } ,
338
381
_ => None ,
339
382
}
340
383
}
@@ -347,14 +390,20 @@ fn kleene_op(token: &token::Token) -> Option<KleeneOp> {
347
390
fn parse_kleene_op < I > (
348
391
input : & mut I ,
349
392
span : Span ,
393
+ sess : & ParseSess ,
394
+ edition : Edition ,
395
+ features : & Features ,
396
+ attrs : & [ ast:: Attribute ] ,
350
397
) -> Result < Result < KleeneOp , ( token:: Token , Span ) > , Span >
351
398
where
352
399
I : Iterator < Item = tokenstream:: TokenTree > ,
353
400
{
354
401
match input. next ( ) {
355
- Some ( tokenstream:: TokenTree :: Token ( span, tok) ) => match kleene_op ( & tok) {
356
- Some ( op) => Ok ( Ok ( op) ) ,
357
- None => Ok ( Err ( ( tok, span) ) ) ,
402
+ Some ( tokenstream:: TokenTree :: Token ( span, tok) ) => {
403
+ match kleene_op ( & tok, span, sess, edition, features, attrs) {
404
+ Some ( op) => Ok ( Ok ( op) ) ,
405
+ None => Ok ( Err ( ( tok, span) ) ) ,
406
+ }
358
407
} ,
359
408
tree => Err ( tree. as_ref ( )
360
409
. map ( tokenstream:: TokenTree :: span)
@@ -380,51 +429,22 @@ fn parse_sep_and_kleene_op<I>(
380
429
sess : & ParseSess ,
381
430
features : & Features ,
382
431
attrs : & [ ast:: Attribute ] ,
432
+ edition : Edition ,
383
433
) -> ( Option < token:: Token > , KleeneOp )
384
434
where
385
435
I : Iterator < Item = tokenstream:: TokenTree > ,
386
436
{
387
437
// We basically look at two token trees here, denoted as #1 and #2 below
388
- 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
- ) ;
402
- }
403
- return ( None , op) ;
404
- }
405
-
406
- // #1 is any KleeneOp (`+`, `*`)
438
+ let span = match parse_kleene_op ( input, span, sess, edition, features, attrs) {
439
+ // #1 is any KleeneOp (`+`, `*`, or `?` (on editions > 2015))
407
440
Ok ( Ok ( op) ) => return ( None , op) ,
408
441
409
442
// #1 is a separator followed by #2, a KleeneOp
410
- Ok ( Err ( ( tok, span) ) ) => match parse_kleene_op ( input, span) {
443
+ Ok ( Err ( ( tok, span) ) ) => match parse_kleene_op ( input, span, sess , edition , features , attrs ) {
411
444
// #2 is a KleeneOp :D
412
445
Ok ( Ok ( op) ) if op == KleeneOp :: ZeroOrOne => {
413
- if !features. macro_at_most_once_rep
414
- && !attr:: contains_name ( attrs, "allow_internal_unstable" )
415
- {
416
- let explain = feature_gate:: EXPLAIN_MACRO_AT_MOST_ONCE_REP ;
417
- emit_feature_err (
418
- sess,
419
- "macro_at_most_once_rep" ,
420
- span,
421
- GateIssue :: Language ,
422
- explain,
423
- ) ;
424
- } else {
425
- sess. span_diagnostic
426
- . span_err ( span, "`?` macro repetition does not allow a separator" ) ;
427
- }
446
+ sess. span_diagnostic
447
+ . span_err ( span, "`?` macro repetition does not allow a separator" ) ;
428
448
return ( None , op) ;
429
449
}
430
450
Ok ( Ok ( op) ) => return ( Some ( tok) , op) ,
0 commit comments