diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-09-19 10:00:24 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-09-19 10:00:24 -0700 |
| commit | 81ee3586b5d75497af25e77756be8f629d711aaf (patch) | |
| tree | 0a34469c940e83723b3c8b1e1413f3f50aaea879 /src/libsyntax | |
| parent | b94075c9cefb3baedd4b0c01c9c11393e83ea66a (diff) | |
| parent | cf9c586fccb1063ea6f75609c702df909d4ac3f1 (diff) | |
| download | rust-81ee3586b5d75497af25e77756be8f629d711aaf.tar.gz rust-81ee3586b5d75497af25e77756be8f629d711aaf.zip | |
rollup merge of #17318 : nick29581/slice
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 105 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 5 |
5 files changed, 131 insertions, 10 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 81f5209ccd9..5c84745c20c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -538,6 +538,7 @@ pub enum Expr_ { ExprField(P<Expr>, SpannedIdent, Vec<P<Ty>>), ExprTupField(P<Expr>, Spanned<uint>, Vec<P<Ty>>), ExprIndex(P<Expr>, P<Expr>), + ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar::<baz> diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1441f5beb6a..7ebb11c148b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1252,6 +1252,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) } + ExprSlice(e, e1, e2, m) => { + ExprSlice(folder.fold_expr(e), + e1.map(|x| folder.fold_expr(x)), + e2.map(|x| folder.fold_expr(x)), + m) + } ExprPath(pth) => ExprPath(folder.fold_path(pth)), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a5a936a9779..069d30cbd83 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -23,7 +23,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; -use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex}; +use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex, ExprSlice}; use ast::{ExprLit, ExprLoop, ExprMac}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn}; @@ -1987,6 +1987,14 @@ impl<'a> Parser<'a> { ExprIndex(expr, idx) } + pub fn mk_slice(&mut self, expr: P<Expr>, + start: Option<P<Expr>>, + end: Option<P<Expr>>, + mutbl: Mutability) + -> ast::Expr_ { + ExprSlice(expr, start, end, mutbl) + } + pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent, tys: Vec<P<Ty>>) -> ast::Expr_ { ExprField(expr, ident, tys) @@ -2401,13 +2409,87 @@ impl<'a> Parser<'a> { } // expr[...] + // Could be either an index expression or a slicing expression. + // Any slicing non-terminal can have a mutable version with `mut` + // after the opening square bracket. token::LBRACKET => { self.bump(); - let ix = self.parse_expr(); - hi = self.span.hi; - self.commit_expr_expecting(&*ix, token::RBRACKET); - let index = self.mk_index(e, ix); - e = self.mk_expr(lo, hi, index) + let mutbl = if self.eat_keyword(keywords::Mut) { + MutMutable + } else { + MutImmutable + }; + match self.token { + // e[] + token::RBRACKET => { + self.bump(); + hi = self.span.hi; + let slice = self.mk_slice(e, None, None, mutbl); + e = self.mk_expr(lo, hi, slice) + } + // e[..e] + token::DOTDOT => { + self.bump(); + match self.token { + // e[..] + token::RBRACKET => { + self.bump(); + hi = self.span.hi; + let slice = self.mk_slice(e, None, None, mutbl); + e = self.mk_expr(lo, hi, slice); + + self.span_err(e.span, "incorrect slicing expression: `[..]`"); + self.span_note(e.span, + "use `expr[]` to construct a slice of the whole of expr"); + } + // e[..e] + _ => { + hi = self.span.hi; + let e2 = self.parse_expr(); + self.commit_expr_expecting(&*e2, token::RBRACKET); + let slice = self.mk_slice(e, None, Some(e2), mutbl); + e = self.mk_expr(lo, hi, slice) + } + } + } + // e[e] | e[e..] | e[e..e] + _ => { + let ix = self.parse_expr(); + match self.token { + // e[e..] | e[e..e] + token::DOTDOT => { + self.bump(); + let e2 = match self.token { + // e[e..] + token::RBRACKET => { + self.bump(); + None + } + // e[e..e] + _ => { + let e2 = self.parse_expr(); + self.commit_expr_expecting(&*e2, token::RBRACKET); + Some(e2) + } + }; + hi = self.span.hi; + let slice = self.mk_slice(e, Some(ix), e2, mutbl); + e = self.mk_expr(lo, hi, slice) + } + // e[e] + _ => { + if mutbl == ast::MutMutable { + self.span_err(e.span, + "`mut` keyword is invalid in index expressions"); + } + hi = self.span.hi; + self.commit_expr_expecting(&*ix, token::RBRACKET); + let index = self.mk_index(e, ix); + e = self.mk_expr(lo, hi, index) + } + } + } + } } _ => return e @@ -3154,7 +3236,8 @@ impl<'a> Parser<'a> { // These expressions are limited to literals (possibly // preceded by unary-minus) or identifiers. let val = self.parse_literal_maybe_minus(); - if self.token == token::DOTDOT && + // FIXME(#17295) remove the DOTDOT option. + if (self.token == token::DOTDOTDOT || self.token == token::DOTDOT) && self.look_ahead(1, |t| { *t != token::COMMA && *t != token::RBRACKET }) { @@ -3199,12 +3282,16 @@ impl<'a> Parser<'a> { } }); - if self.look_ahead(1, |t| *t == token::DOTDOT) && + // FIXME(#17295) remove the DOTDOT option. + if self.look_ahead(1, |t| *t == token::DOTDOTDOT || *t == token::DOTDOT) && self.look_ahead(2, |t| { *t != token::COMMA && *t != token::RBRACKET }) { let start = self.parse_expr_res(RestrictionNoBarOp); - self.eat(&token::DOTDOT); + // FIXME(#17295) remove the DOTDOT option (self.eat(&token::DOTDOTDOT)). + if self.token == token::DOTDOTDOT || self.token == token::DOTDOT { + self.bump(); + } let end = self.parse_expr_res(RestrictionNoBarOp); pat = PatRange(start, end); } else if is_plain_ident(&self.token) && !can_be_enum_or_struct { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d7dd87a096e..473179a037a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1651,6 +1651,28 @@ impl<'a> State<'a> { try!(self.print_expr(&**index)); try!(word(&mut self.s, "]")); } + ast::ExprSlice(ref e, ref start, ref end, ref mutbl) => { + try!(self.print_expr(&**e)); + try!(word(&mut self.s, "[")); + if mutbl == &ast::MutMutable { + try!(word(&mut self.s, "mut")); + if start.is_some() || end.is_some() { + try!(space(&mut self.s)); + } + } + match start { + &Some(ref e) => try!(self.print_expr(&**e)), + _ => {} + } + if start.is_some() || end.is_some() { + try!(word(&mut self.s, "..")); + } + match end { + &Some(ref e) => try!(self.print_expr(&**e)), + _ => {} + } + try!(word(&mut self.s, "]")); + } ast::ExprPath(ref path) => try!(self.print_path(path, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); @@ -1944,7 +1966,7 @@ impl<'a> State<'a> { ast::PatRange(ref begin, ref end) => { try!(self.print_expr(&**begin)); try!(space(&mut self.s)); - try!(word(&mut self.s, "..")); + try!(word(&mut self.s, "...")); try!(self.print_expr(&**end)); } ast::PatVec(ref before, ref slice, ref after) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d425c60f4c9..32084856817 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -785,6 +785,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(&**main_expression); visitor.visit_expr(&**index_expression) } + ExprSlice(ref main_expression, ref start, ref end, _) => { + visitor.visit_expr(&**main_expression); + walk_expr_opt(visitor, start); + walk_expr_opt(visitor, end) + } ExprPath(ref path) => { visitor.visit_path(path, expression.id) } |
