From 5d8cfd53b513d999ffff22f17e3066a30a8ed949 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sun, 24 Aug 2014 18:04:29 -0700 Subject: Teach libsyntax about `if let` --- src/libsyntax/parse/classify.rs | 1 + src/libsyntax/parse/parser.rs | 35 ++++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index cdd221aca7c..cb57318445e 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -24,6 +24,7 @@ use ast; pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { match e.node { ast::ExprIf(..) + | ast::ExprIfLet(..) | ast::ExprMatch(..) | ast::ExprBlock(_) | ast::ExprWhile(..) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 415ff6a4097..d4ba81c737b 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, ExprSlice}; +use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; use ast::{ExprLit, ExprLoop, ExprMac}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn}; @@ -576,13 +576,10 @@ impl<'a> Parser<'a> { /// If the next token is the given keyword, eat it and return /// true. Otherwise, return false. pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool { - match self.token { - token::IDENT(sid, false) if kw.to_name() == sid.name => { - self.bump(); - true - } - _ => false - } + if self.is_keyword(kw) { + self.bump(); + true + } else { false } } /// If the given word is not a keyword, signal an error. @@ -2860,8 +2857,11 @@ impl<'a> Parser<'a> { } } - /// Parse an 'if' expression ('if' token already eaten) + /// Parse an 'if' or 'if let' expression ('if' token already eaten) pub fn parse_if_expr(&mut self) -> P { + if self.is_keyword(keywords::Let) { + return self.parse_if_let_expr(); + } let lo = self.last_span.lo; let cond = self.parse_expr_res(RestrictionNoStructLiteral); let thn = self.parse_block(); @@ -2875,6 +2875,23 @@ impl<'a> Parser<'a> { self.mk_expr(lo, hi, ExprIf(cond, thn, els)) } + /// Parse an 'if let' expression ('if' token already eaten) + pub fn parse_if_let_expr(&mut self) -> P { + let lo = self.last_span.lo; + self.expect_keyword(keywords::Let); + let pat = self.parse_pat(); + self.expect(&token::EQ); + let expr = self.parse_expr_res(RestrictionNoStructLiteral); + let thn = self.parse_block(); + let (hi, els) = if self.eat_keyword(keywords::Else) { + let expr = self.parse_else_expr(); + (expr.span.hi, Some(expr)) + } else { + (thn.span.hi, None) + }; + self.mk_expr(lo, hi, ExprIfLet(pat, expr, thn, els)) + } + // `|args| expr` pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause) -> P { -- cgit 1.4.1-3-g733a5