diff options
| author | Oliver Schneider <git-no-reply-9879165716479413131@oli-obk.de> | 2017-01-10 22:13:53 +0100 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2017-01-19 10:13:32 +0100 |
| commit | c951341a78a9d3cc7c73130ca08cbc273af72082 (patch) | |
| tree | 8f1fcf8edef8caa33ef15f5121e66d10981e00e4 /src/libsyntax | |
| parent | 74c42ac173bee900979870ed986c760596d1fbdb (diff) | |
| download | rust-c951341a78a9d3cc7c73130ca08cbc273af72082.tar.gz rust-c951341a78a9d3cc7c73130ca08cbc273af72082.zip | |
add exclusive range patterns under a feature gate
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 43 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 4 |
6 files changed, 67 insertions, 22 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 58487655ac1..d18215be3e6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -548,6 +548,12 @@ pub enum BindingMode { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum RangeEnd { + Included, + Excluded, +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`) Wild, @@ -583,8 +589,8 @@ pub enum PatKind { Ref(P<Pat>, Mutability), /// A literal Lit(P<Expr>), - /// A range pattern, e.g. `1...2` - Range(P<Expr>, P<Expr>), + /// A range pattern, e.g. `1...2` or `1..2` + Range(P<Expr>, P<Expr>, RangeEnd), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ba6e752d310..17b9fdf2e7c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -26,7 +26,7 @@ use self::AttributeType::*; use self::AttributeGate::*; use abi::Abi; -use ast::{self, NodeId, PatKind}; +use ast::{self, NodeId, PatKind, RangeEnd}; use attr; use codemap::{CodeMap, Spanned}; use syntax_pos::Span; @@ -248,6 +248,9 @@ declare_features! ( // a...b and ...b (active, inclusive_range_syntax, "1.7.0", Some(28237)), + // X..Y patterns + (active, exclusive_range_pattern, "1.11.0", Some(37854)), + // impl specialization (RFC 1210) (active, specialization, "1.7.0", Some(31844)), @@ -1262,6 +1265,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } } + PatKind::Range(_, _, RangeEnd::Excluded) => { + gate_feature_post!(&self, exclusive_range_pattern, pattern.span, + "exclusive range pattern syntax is experimental"); + } _ => {} } visit::walk_pat(self, pattern) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2e5ce739fb3..bc8d13d800c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -112,6 +112,10 @@ pub trait Folder : Sized { e.map(|e| noop_fold_expr(e, self)) } + fn fold_range_end(&mut self, re: RangeEnd) -> RangeEnd { + noop_fold_range_end(re, self) + } + fn fold_opt_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> { noop_fold_opt_expr(e, self) } @@ -1095,8 +1099,10 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { } PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), - PatKind::Range(e1, e2) => { - PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2)) + PatKind::Range(e1, e2, end) => { + PatKind::Range(folder.fold_expr(e1), + folder.fold_expr(e2), + folder.fold_range_end(end)) }, PatKind::Slice(before, slice, after) => { PatKind::Slice(before.move_map(|x| folder.fold_pat(x)), @@ -1109,6 +1115,10 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { }) } +pub fn noop_fold_range_end<T: Folder>(end: RangeEnd, _folder: &mut T) -> RangeEnd { + end +} + pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr { Expr { node: match node { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d1a683b0bd5..1ddfa16e622 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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}; @@ -3445,8 +3446,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)) { @@ -3462,8 +3462,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 { @@ -3578,6 +3577,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); @@ -3627,11 +3642,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 @@ -3658,14 +3669,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() { @@ -3699,7 +3715,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); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index baa3ebec854..2c513df88de 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,7 +11,7 @@ pub use self::AnnNode::*; use abi::{self, Abi}; -use ast::{self, BlockCheckMode, PatKind}; +use ast::{self, BlockCheckMode, PatKind, RangeEnd}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; use util::parser::AssocOp; @@ -2553,10 +2553,13 @@ impl<'a> State<'a> { self.print_pat(&inner)?; } PatKind::Lit(ref e) => self.print_expr(&**e)?, - PatKind::Range(ref begin, ref end) => { + PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(&begin)?; space(&mut self.s)?; - word(&mut self.s, "...")?; + match *end_kind { + RangeEnd::Included => word(&mut self.s, "...")?, + RangeEnd::Excluded => word(&mut self.s, "..")?, + } self.print_expr(&end)?; } PatKind::Slice(ref before, ref slice, ref after) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 1fcfce18948..bfab7a250c6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -440,9 +440,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { walk_list!(visitor, visit_pat, optional_subpattern); } PatKind::Lit(ref expression) => visitor.visit_expr(expression), - PatKind::Range(ref lower_bound, ref upper_bound) => { + PatKind::Range(ref lower_bound, ref upper_bound, _) => { visitor.visit_expr(lower_bound); - visitor.visit_expr(upper_bound) + visitor.visit_expr(upper_bound); } PatKind::Wild => (), PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => { |
