about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-13 19:16:28 +0000
committerbors <bors@rust-lang.org>2014-07-13 19:16:28 +0000
commit7a6208f2cc1bbe29dc42b21d27e98894b8bacc04 (patch)
treed4341cdd32f5d747a6289b2335012ec8f435d151 /src/libsyntax/parse/parser.rs
parentfbeee04f31ac16fe61f29749145a29e562d065fe (diff)
parentaee5917556856428072cc090fb892176eaa075b3 (diff)
downloadrust-7a6208f2cc1bbe29dc42b21d27e98894b8bacc04.tar.gz
rust-7a6208f2cc1bbe29dc42b21d27e98894b8bacc04.zip
auto merge of #15646 : jbclements/rust/method-macros, r=cmr
This patch adds support for macros in method position. It follows roughly the template for Item macros, where an outer `Method` wrapper contains a `Method_` enum which can either be a macro invocation or a standard macro definition. 

One note; adding support for macros that expand into multiple methods is not included here, but should be a simple parser change, since this patch updates the type of fold_macro to return a smallvector of methods.

For reviewers, please pay special attention to the parser changes; these are the ones I'm most concerned about.

Because of the small change to the interface of fold_method, this is a ...

[breaking change]
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs69
1 files changed, 43 insertions, 26 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 84db2bc5a22..e0c94dffb5c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1249,16 +1249,10 @@ impl<'a> Parser<'a> {
                     p.parse_inner_attrs_and_block();
                 let attrs = attrs.append(inner_attrs.as_slice());
                 Provided(box(GC) ast::Method {
-                    ident: ident,
                     attrs: attrs,
-                    generics: generics,
-                    explicit_self: explicit_self,
-                    fn_style: style,
-                    decl: d,
-                    body: body,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
-                    vis: vis,
+                    node: ast::MethDecl(ident, generics, explicit_self, style, d, body, vis)
                 })
               }
 
@@ -3252,6 +3246,7 @@ impl<'a> Parser<'a> {
         } else if is_ident(&self.token)
             && !token::is_any_keyword(&self.token)
             && self.look_ahead(1, |t| *t == token::NOT) {
+            // it's a macro invocation:
 
             check_expected_item(self, !item_attrs.is_empty());
 
@@ -4027,7 +4022,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a method in a trait impl, starting with `attrs` attributes.
-    fn parse_method(&mut self,
+    pub fn parse_method(&mut self,
                     already_parsed_attrs: Option<Vec<Attribute>>) -> Gc<Method> {
         let next_attrs = self.parse_outer_attributes();
         let attrs = match already_parsed_attrs {
@@ -4037,28 +4032,50 @@ impl<'a> Parser<'a> {
 
         let lo = self.span.lo;
 
-        let visa = self.parse_visibility();
-        let fn_style = self.parse_fn_style();
-        let ident = self.parse_ident();
-        let generics = self.parse_generics();
-        let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| {
-            p.parse_arg()
-        });
+        // code copied from parse_macro_use_or_failure... abstraction!
+        let (method_, hi, new_attrs) = {
+            if !token::is_any_keyword(&self.token)
+                && self.look_ahead(1, |t| *t == token::NOT)
+                && (self.look_ahead(2, |t| *t == token::LPAREN)
+                    || self.look_ahead(2, |t| *t == token::LBRACE)) {
+                // method macro.
+                let pth = self.parse_path(NoTypesAllowed).path;
+                self.expect(&token::NOT);
 
-        let (inner_attrs, body) = self.parse_inner_attrs_and_block();
-        let hi = body.span.hi;
-        let attrs = attrs.append(inner_attrs.as_slice());
+                // eat a matched-delimiter token tree:
+                let tts = match token::close_delimiter_for(&self.token) {
+                    Some(ket) => {
+                        self.bump();
+                        self.parse_seq_to_end(&ket,
+                                              seq_sep_none(),
+                                              |p| p.parse_token_tree())
+                    }
+                    None => self.fatal("expected open delimiter")
+                };
+                let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
+                let m: ast::Mac = codemap::Spanned { node: m_,
+                                                 span: mk_sp(self.span.lo,
+                                                             self.span.hi) };
+                (ast::MethMac(m), self.span.hi, attrs)
+            } else {
+                let visa = self.parse_visibility();
+                let fn_style = self.parse_fn_style();
+                let ident = self.parse_ident();
+                let generics = self.parse_generics();
+                let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| {
+                        p.parse_arg()
+                    });
+                let (inner_attrs, body) = self.parse_inner_attrs_and_block();
+                let new_attrs = attrs.append(inner_attrs.as_slice());
+                (ast::MethDecl(ident, generics, explicit_self, fn_style, decl, body, visa),
+                 body.span.hi, new_attrs)
+            }
+        };
         box(GC) ast::Method {
-            ident: ident,
-            attrs: attrs,
-            generics: generics,
-            explicit_self: explicit_self,
-            fn_style: fn_style,
-            decl: decl,
-            body: body,
+            attrs: new_attrs,
             id: ast::DUMMY_NODE_ID,
             span: mk_sp(lo, hi),
-            vis: visa,
+            node: method_,
         }
     }