diff options
| author | kennytm <kennytm@gmail.com> | 2018-06-08 07:05:47 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-08 07:05:47 +0800 |
| commit | e46ef1bb86f9f206da06e9d5b313f0ca31809832 (patch) | |
| tree | 54c644daab720e9e3f2b45aaf8e1969c4c2aae8c /src/libsyntax/ext | |
| parent | c843607bcc282a14cd1e17342eaa17ff0223ccfa (diff) | |
| parent | 1df781712297270c74d175552e420ae055a7f193 (diff) | |
| download | rust-e46ef1bb86f9f206da06e9d5b313f0ca31809832.tar.gz rust-e46ef1bb86f9f206da06e9d5b313f0ca31809832.zip | |
Rollup merge of #51417 - pietroalbini:revert-49719, r=nikomatsakis
Revert #49719 This also needs to be backported into beta. Fixes #51416. r? @nikomatsakis
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/tt/quoted.rs | 89 |
1 files changed, 67 insertions, 22 deletions
diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 77c6afa1c64..01b971976a7 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -386,26 +386,72 @@ where { // We basically look at two token trees here, denoted as #1 and #2 below let span = match parse_kleene_op(input, span) { - // #1 is any KleeneOp (`?`) - Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { - if !features.macro_at_most_once_rep - && !attr::contains_name(attrs, "allow_internal_unstable") - { - let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; - emit_feature_err( - sess, - "macro_at_most_once_rep", - span, - GateIssue::Language, - explain, - ); + // #1 is a `+` or `*` KleeneOp + // + // `?` is ambiguous: it could be a separator or a Kleene::ZeroOrOne, so we need to look + // ahead one more token to be sure. + Ok(Ok(op)) if op != KleeneOp::ZeroOrOne => return (None, op), + + // #1 is `?` token, but it could be a Kleene::ZeroOrOne without a separator or it could + // be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to + // find out which. + Ok(Ok(op)) => { + assert_eq!(op, KleeneOp::ZeroOrOne); + + // Lookahead at #2. If it is a KleenOp, then #1 is a separator. + let is_1_sep = if let Some(&tokenstream::TokenTree::Token(_, ref tok2)) = input.peek() { + kleene_op(tok2).is_some() + } else { + false + }; + + if is_1_sep { + // #1 is a separator and #2 should be a KleepeOp::* + // (N.B. We need to advance the input iterator.) + match parse_kleene_op(input, span) { + // #2 is a KleeneOp (this is the only valid option) :) + Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { + if !features.macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; + emit_feature_err( + sess, + "macro_at_most_once_rep", + span, + GateIssue::Language, + explain, + ); + } + return (Some(token::Question), op); + } + Ok(Ok(op)) => return (Some(token::Question), op), + + // #2 is a random token (this is an error) :( + Ok(Err((_, span))) => span, + + // #2 is not even a token at all :( + Err(span) => span, + } + } else { + if !features.macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { + let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; + emit_feature_err( + sess, + "macro_at_most_once_rep", + span, + GateIssue::Language, + explain, + ); + } + + // #2 is a random tree and #1 is KleeneOp::ZeroOrOne + return (None, op); } - return (None, op); } - // #1 is any KleeneOp (`+`, `*`) - Ok(Ok(op)) => return (None, op), - // #1 is a separator followed by #2, a KleeneOp Ok(Err((tok, span))) => match parse_kleene_op(input, span) { // #2 is a KleeneOp :D @@ -421,11 +467,8 @@ where GateIssue::Language, explain, ); - } else { - sess.span_diagnostic - .span_err(span, "`?` macro repetition does not allow a separator"); } - return (None, op); + return (Some(tok), op); } Ok(Ok(op)) => return (Some(tok), op), @@ -440,7 +483,9 @@ where Err(span) => span, }; - if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { + if !features.macro_at_most_once_rep + && !attr::contains_name(attrs, "allow_internal_unstable") + { sess.span_diagnostic .span_err(span, "expected one of: `*`, `+`, or `?`"); } else { |
