Skip to content

Commit 39fbcfb

Browse files
committed
Support ? Kleene operator in 2015.
1 parent 053666f commit 39fbcfb

File tree

1 file changed

+4
-167
lines changed

1 file changed

+4
-167
lines changed

src/libsyntax/ext/tt/quoted.rs

Lines changed: 4 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::ast::NodeId;
2-
use crate::early_buffered_lints::BufferedEarlyLintId;
32
use crate::ext::tt::macro_parser;
43
use crate::feature_gate::Features;
54
use crate::parse::token::{self, Token, TokenKind};
@@ -287,16 +286,7 @@ where
287286
macro_node_id,
288287
);
289288
// Get the Kleene operator and optional separator
290-
let (separator, op) =
291-
parse_sep_and_kleene_op(
292-
trees,
293-
span.entire(),
294-
sess,
295-
features,
296-
attrs,
297-
edition,
298-
macro_node_id,
299-
);
289+
let (separator, op) = parse_sep_and_kleene_op(trees, span.entire(), sess);
300290
// Count the number of captured "names" (i.e., named metavars)
301291
let name_captures = macro_parser::count_names(&sequence);
302292
TokenTree::Sequence(
@@ -403,164 +393,11 @@ where
403393
/// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene
404394
/// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an
405395
/// error with the appropriate span is emitted to `sess` and a dummy value is returned.
406-
///
407-
/// N.B., in the 2015 edition, `*` and `+` are the only Kleene operators, and `?` is a separator.
408-
/// In the 2018 edition however, `?` is a Kleene operator, and not a separator.
409-
fn parse_sep_and_kleene_op<I>(
410-
input: &mut Peekable<I>,
411-
span: Span,
412-
sess: &ParseSess,
413-
features: &Features,
414-
attrs: &[ast::Attribute],
415-
edition: Edition,
416-
macro_node_id: NodeId,
417-
) -> (Option<Token>, KleeneOp)
418-
where
419-
I: Iterator<Item = tokenstream::TokenTree>,
420-
{
421-
match edition {
422-
Edition::Edition2015 => parse_sep_and_kleene_op_2015(
423-
input,
424-
span,
425-
sess,
426-
features,
427-
attrs,
428-
macro_node_id,
429-
),
430-
Edition::Edition2018 => parse_sep_and_kleene_op_2018(input, span, sess, features, attrs),
431-
}
432-
}
433-
434-
// `?` is a separator (with a migration warning) and never a KleeneOp.
435-
fn parse_sep_and_kleene_op_2015<I>(
436-
input: &mut Peekable<I>,
437-
span: Span,
438-
sess: &ParseSess,
439-
_features: &Features,
440-
_attrs: &[ast::Attribute],
441-
macro_node_id: NodeId,
442-
) -> (Option<Token>, KleeneOp)
443-
where
444-
I: Iterator<Item = tokenstream::TokenTree>,
445-
{
446-
// We basically look at two token trees here, denoted as #1 and #2 below
447-
let span = match parse_kleene_op(input, span) {
448-
// #1 is a `+` or `*` KleeneOp
449-
//
450-
// `?` is ambiguous: it could be a separator (warning) or a Kleene::ZeroOrOne (error), so
451-
// we need to look ahead one more token to be sure.
452-
Ok(Ok((op, _))) if op != KleeneOp::ZeroOrOne => return (None, op),
453-
454-
// #1 is `?` token, but it could be a Kleene::ZeroOrOne (error in 2015) without a separator
455-
// or it could be a `?` separator followed by any Kleene operator. We need to look ahead 1
456-
// token to find out which.
457-
Ok(Ok((op, op1_span))) => {
458-
assert_eq!(op, KleeneOp::ZeroOrOne);
459-
460-
// Lookahead at #2. If it is a KleenOp, then #1 is a separator.
461-
let is_1_sep = if let Some(tokenstream::TokenTree::Token(tok2)) = input.peek() {
462-
kleene_op(tok2).is_some()
463-
} else {
464-
false
465-
};
466-
467-
if is_1_sep {
468-
// #1 is a separator and #2 should be a KleepeOp.
469-
// (N.B. We need to advance the input iterator.)
470-
match parse_kleene_op(input, span) {
471-
// #2 is `?`, which is not allowed as a Kleene op in 2015 edition,
472-
// but is allowed in the 2018 edition.
473-
Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
474-
sess.span_diagnostic
475-
.struct_span_err(op2_span, "expected `*` or `+`")
476-
.note("`?` is not a macro repetition operator in the 2015 edition, \
477-
but is accepted in the 2018 edition")
478-
.emit();
479-
480-
// Return a dummy
481-
return (None, KleeneOp::ZeroOrMore);
482-
}
483-
484-
// #2 is a Kleene op, which is the only valid option
485-
Ok(Ok((op, _))) => {
486-
// Warn that `?` as a separator will be deprecated
487-
sess.buffer_lint(
488-
BufferedEarlyLintId::QuestionMarkMacroSep,
489-
op1_span,
490-
macro_node_id,
491-
"using `?` as a separator is deprecated and will be \
492-
a hard error in an upcoming edition",
493-
);
494-
495-
return (Some(Token::new(token::Question, op1_span)), op);
496-
}
497-
498-
// #2 is a random token (this is an error) :(
499-
Ok(Err(_)) => op1_span,
500-
501-
// #2 is not even a token at all :(
502-
Err(_) => op1_span,
503-
}
504-
} else {
505-
// `?` is not allowed as a Kleene op in 2015,
506-
// but is allowed in the 2018 edition
507-
sess.span_diagnostic
508-
.struct_span_err(op1_span, "expected `*` or `+`")
509-
.note("`?` is not a macro repetition operator in the 2015 edition, \
510-
but is accepted in the 2018 edition")
511-
.emit();
512-
513-
// Return a dummy
514-
return (None, KleeneOp::ZeroOrMore);
515-
}
516-
}
517-
518-
// #1 is a separator followed by #2, a KleeneOp
519-
Ok(Err(token)) => match parse_kleene_op(input, token.span) {
520-
// #2 is a `?`, which is not allowed as a Kleene op in 2015 edition,
521-
// but is allowed in the 2018 edition
522-
Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
523-
sess.span_diagnostic
524-
.struct_span_err(op2_span, "expected `*` or `+`")
525-
.note("`?` is not a macro repetition operator in the 2015 edition, \
526-
but is accepted in the 2018 edition")
527-
.emit();
528-
529-
// Return a dummy
530-
return (None, KleeneOp::ZeroOrMore);
531-
}
532-
533-
// #2 is a KleeneOp :D
534-
Ok(Ok((op, _))) => return (Some(token), op),
535-
536-
// #2 is a random token :(
537-
Ok(Err(token)) => token.span,
538-
539-
// #2 is not a token at all :(
540-
Err(span) => span,
541-
},
542-
543-
// #1 is not a token
544-
Err(span) => span,
545-
};
546-
547-
sess.span_diagnostic.span_err(span, "expected `*` or `+`");
548-
549-
// Return a dummy
550-
(None, KleeneOp::ZeroOrMore)
551-
}
552-
553-
// `?` is a Kleene op, not a separator
554-
fn parse_sep_and_kleene_op_2018<I>(
555-
input: &mut Peekable<I>,
396+
fn parse_sep_and_kleene_op(
397+
input: &mut Peekable<impl Iterator<Item = tokenstream::TokenTree>>,
556398
span: Span,
557399
sess: &ParseSess,
558-
_features: &Features,
559-
_attrs: &[ast::Attribute],
560-
) -> (Option<Token>, KleeneOp)
561-
where
562-
I: Iterator<Item = tokenstream::TokenTree>,
563-
{
400+
) -> (Option<Token>, KleeneOp) {
564401
// We basically look at two token trees here, denoted as #1 and #2 below
565402
let span = match parse_kleene_op(input, span) {
566403
// #1 is a `?` (needs feature gate)

0 commit comments

Comments
 (0)