Auto merge of #35712 - oli-obk:exclusive_range_patterns, r=nikomatsakis
exclusive range patterns adds `..` patterns to the language under a feature gate (`exclusive_range_pattern`). This allows turning ``` rust match i { 0...9 => {}, 10...19 => {}, 20...29 => {}, _ => {} } ``` into ``` rust match i { 0..10 => {}, 10..20 => {}, 20..30 => {}, _ => {} } ```
This commit is contained in:
commit
c0d0e68be4
25 changed files with 269 additions and 67 deletions
|
@ -38,6 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
|
|||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use ast::{Visibility, WhereClause};
|
||||
use ast::{BinOpKind, UnOp};
|
||||
use ast::RangeEnd;
|
||||
use {ast, attr};
|
||||
use codemap::{self, CodeMap, Spanned, spanned, respan};
|
||||
use syntax_pos::{self, Span, Pos, BytePos, mk_sp};
|
||||
|
@ -3329,8 +3330,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
if before_slice {
|
||||
if self.check(&token::DotDot) {
|
||||
self.bump();
|
||||
if self.eat(&token::DotDot) {
|
||||
|
||||
if self.check(&token::Comma) ||
|
||||
self.check(&token::CloseDelim(token::Bracket)) {
|
||||
|
@ -3346,8 +3346,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
let subpat = self.parse_pat()?;
|
||||
if before_slice && self.check(&token::DotDot) {
|
||||
self.bump();
|
||||
if before_slice && self.eat(&token::DotDot) {
|
||||
slice = Some(subpat);
|
||||
before_slice = false;
|
||||
} else if before_slice {
|
||||
|
@ -3462,6 +3461,22 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// helper function to decide whether to parse as ident binding or to try to do
|
||||
// something more complex like range patterns
|
||||
fn parse_as_ident(&mut self) -> bool {
|
||||
self.look_ahead(1, |t| match *t {
|
||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
||||
token::DotDotDot | token::ModSep | token::Not => Some(false),
|
||||
// ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
|
||||
// range pattern branch
|
||||
token::DotDot => None,
|
||||
_ => Some(true),
|
||||
}).unwrap_or_else(|| self.look_ahead(2, |t| match *t {
|
||||
token::Comma | token::CloseDelim(token::Bracket) => true,
|
||||
_ => false,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parse a pattern.
|
||||
pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
|
||||
maybe_whole!(self, NtPat, |x| x);
|
||||
|
@ -3511,11 +3526,7 @@ impl<'a> Parser<'a> {
|
|||
let subpat = self.parse_pat()?;
|
||||
pat = PatKind::Box(subpat);
|
||||
} else if self.token.is_ident() && !self.token.is_any_keyword() &&
|
||||
self.look_ahead(1, |t| match *t {
|
||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
||||
token::DotDotDot | token::ModSep | token::Not => false,
|
||||
_ => true,
|
||||
}) {
|
||||
self.parse_as_ident() {
|
||||
// Parse ident @ pat
|
||||
// This can give false positives and parse nullary enums,
|
||||
// they are dealt with later in resolve
|
||||
|
@ -3542,14 +3553,19 @@ impl<'a> Parser<'a> {
|
|||
let mac = spanned(lo, self.prev_span.hi, Mac_ { path: path, tts: tts });
|
||||
pat = PatKind::Mac(mac);
|
||||
}
|
||||
token::DotDotDot => {
|
||||
token::DotDotDot | token::DotDot => {
|
||||
let end_kind = match self.token {
|
||||
token::DotDot => RangeEnd::Excluded,
|
||||
token::DotDotDot => RangeEnd::Included,
|
||||
_ => panic!("can only parse `..` or `...` for ranges (checked above)"),
|
||||
};
|
||||
// Parse range
|
||||
let hi = self.prev_span.hi;
|
||||
let begin =
|
||||
self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new());
|
||||
self.bump();
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end);
|
||||
pat = PatKind::Range(begin, end, end_kind);
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
if qself.is_some() {
|
||||
|
@ -3583,7 +3599,10 @@ impl<'a> Parser<'a> {
|
|||
Ok(begin) => {
|
||||
if self.eat(&token::DotDotDot) {
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end);
|
||||
pat = PatKind::Range(begin, end, RangeEnd::Included);
|
||||
} else if self.eat(&token::DotDot) {
|
||||
let end = self.parse_pat_range_end()?;
|
||||
pat = PatKind::Range(begin, end, RangeEnd::Excluded);
|
||||
} else {
|
||||
pat = PatKind::Lit(begin);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue