about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-03-14 10:40:09 +0000
committerbors <bors@rust-lang.org>2017-03-14 10:40:09 +0000
commit6f10e2f63de720468e2b4bfcb275e4b90b1f9870 (patch)
tree11f51d7f07c5a74ab22e20b7f3556c4c0191fe66 /src/libsyntax/parse
parentfa53235cc4364fe085ccba720237d19b669c2f8b (diff)
parentb1aa99352a69e328094e096bbbd1741b68c0667f (diff)
downloadrust-6f10e2f63de720468e2b4bfcb275e4b90b1f9870.tar.gz
rust-6f10e2f63de720468e2b4bfcb275e4b90b1f9870.zip
Auto merge of #39921 - cramertj:add-catch-to-ast, r=nikomatsakis
Add catch {} to AST

Part of #39849. Builds on #39864.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs27
-rw-r--r--src/libsyntax/parse/token.rs1
2 files changed, 28 insertions, 0 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ff7918cc278..8f66c1a2b8c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2280,6 +2280,12 @@ impl<'a> Parser<'a> {
                         BlockCheckMode::Unsafe(ast::UserProvided),
                         attrs);
                 }
+                if self.is_catch_expr() {
+                    assert!(self.eat_keyword(keywords::Do));
+                    assert!(self.eat_keyword(keywords::Catch));
+                    let lo = self.prev_span.lo;
+                    return self.parse_catch_expr(lo, attrs);
+                }
                 if self.eat_keyword(keywords::Return) {
                     if self.token.can_begin_expr() {
                         let e = self.parse_expr()?;
@@ -3099,6 +3105,16 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
     }
 
+    /// Parse a `do catch {...}` expression (`do catch` token already eaten)
+    pub fn parse_catch_expr(&mut self, span_lo: BytePos, mut attrs: ThinVec<Attribute>)
+        -> PResult<'a, P<Expr>>
+    {
+        let (iattrs, body) = self.parse_inner_attrs_and_block()?;
+        attrs.extend(iattrs);
+        let hi = body.span.hi;
+        Ok(self.mk_expr(span_lo, hi, ExprKind::Catch(body), attrs))
+    }
+
     // `match` token already eaten
     fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let match_span = self.prev_span;
@@ -3706,6 +3722,15 @@ impl<'a> Parser<'a> {
         })
     }
 
+    fn is_catch_expr(&mut self) -> bool {
+        self.token.is_keyword(keywords::Do) &&
+        self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
+        self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
+
+        // prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
+        !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)
+    }
+
     fn is_union_item(&self) -> bool {
         self.token.is_keyword(keywords::Union) &&
         self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
@@ -4882,6 +4907,7 @@ impl<'a> Parser<'a> {
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
         let class_name = self.parse_ident()?;
+
         let mut generics = self.parse_generics()?;
 
         // There is a special case worth noting here, as reported in issue #17904.
@@ -4931,6 +4957,7 @@ impl<'a> Parser<'a> {
     /// Parse union Foo { ... }
     fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
         let class_name = self.parse_ident()?;
+
         let mut generics = self.parse_generics()?;
 
         let vdata = if self.token.is_keyword(keywords::Where) {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 5b65aac92b8..25601f2420e 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -86,6 +86,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
     !ident_token.is_any_keyword() ||
     ident_token.is_path_segment_keyword() ||
     [
+        keywords::Do.name(),
         keywords::Box.name(),
         keywords::Break.name(),
         keywords::Continue.name(),