88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- pub use self :: SyntaxExtension :: * ;
11+ pub use self :: SyntaxExtension :: { MultiDecorator , MultiModifier , NormalTT , IdentTT , MacroRulesTT } ;
1212
1313use ast:: { self , Attribute , Name , PatKind } ;
1414use attr:: HasAttrs ;
@@ -19,7 +19,7 @@ use ext::expand::{self, Invocation, Expansion};
1919use ext:: hygiene:: Mark ;
2020use ext:: tt:: macro_rules;
2121use parse;
22- use parse:: parser;
22+ use parse:: parser:: { self , Parser } ;
2323use parse:: token;
2424use parse:: token:: { InternedString , str_to_ident} ;
2525use ptr:: P ;
@@ -31,7 +31,8 @@ use feature_gate;
3131use std:: collections:: HashMap ;
3232use std:: path:: PathBuf ;
3333use std:: rc:: Rc ;
34- use tokenstream;
34+ use std:: default:: Default ;
35+ use tokenstream:: { self , TokenStream } ;
3536
3637
3738#[ derive( Debug , Clone ) ]
@@ -60,6 +61,14 @@ impl HasAttrs for Annotatable {
6061}
6162
6263impl Annotatable {
64+ pub fn span ( & self ) -> Span {
65+ match * self {
66+ Annotatable :: Item ( ref item) => item. span ,
67+ Annotatable :: TraitItem ( ref trait_item) => trait_item. span ,
68+ Annotatable :: ImplItem ( ref impl_item) => impl_item. span ,
69+ }
70+ }
71+
6372 pub fn expect_item ( self ) -> P < ast:: Item > {
6473 match self {
6574 Annotatable :: Item ( i) => i,
@@ -146,6 +155,173 @@ impl Into<Vec<Annotatable>> for Annotatable {
146155 }
147156}
148157
158+ pub trait ProcMacro {
159+ fn expand < ' cx > ( & self ,
160+ ecx : & ' cx mut ExtCtxt ,
161+ span : Span ,
162+ ts : TokenStream )
163+ -> Box < MacResult +' cx > ;
164+ }
165+
166+ impl < F > ProcMacro for F
167+ where F : Fn ( TokenStream ) -> TokenStream
168+ {
169+ fn expand < ' cx > ( & self ,
170+ ecx : & ' cx mut ExtCtxt ,
171+ span : Span ,
172+ ts : TokenStream )
173+ -> Box < MacResult +' cx > {
174+ let result = ( * self ) ( ts) ;
175+ // FIXME setup implicit context in TLS before calling self.
176+ let parser = ecx. new_parser_from_tts ( & result. to_tts ( ) ) ;
177+ Box :: new ( TokResult { parser : parser, span : span } )
178+ }
179+ }
180+
181+ pub trait AttrProcMacro {
182+ fn expand < ' cx > ( & self ,
183+ ecx : & ' cx mut ExtCtxt ,
184+ span : Span ,
185+ annotation : TokenStream ,
186+ annotated : TokenStream )
187+ -> Box < MacResult +' cx > ;
188+ }
189+
190+ impl < F > AttrProcMacro for F
191+ where F : Fn ( TokenStream , TokenStream ) -> TokenStream
192+ {
193+ fn expand < ' cx > ( & self ,
194+ ecx : & ' cx mut ExtCtxt ,
195+ span : Span ,
196+ annotation : TokenStream ,
197+ annotated : TokenStream )
198+ -> Box < MacResult +' cx > {
199+ // FIXME setup implicit context in TLS before calling self.
200+ let parser = ecx. new_parser_from_tts ( & ( * self ) ( annotation, annotated) . to_tts ( ) ) ;
201+ Box :: new ( TokResult { parser : parser, span : span } )
202+ }
203+ }
204+
205+ struct TokResult < ' a > {
206+ parser : Parser < ' a > ,
207+ span : Span ,
208+ }
209+
210+ impl < ' a > MacResult for TokResult < ' a > {
211+ fn make_items ( mut self : Box < Self > ) -> Option < SmallVector < P < ast:: Item > > > {
212+ if self . parser . sess . span_diagnostic . has_errors ( ) {
213+ return None ;
214+ }
215+
216+ let mut items = SmallVector :: zero ( ) ;
217+ loop {
218+ match self . parser . parse_item ( ) {
219+ Ok ( Some ( item) ) => {
220+ // FIXME better span info.
221+ let mut item = item. unwrap ( ) ;
222+ item. span = self . span ;
223+ items. push ( P ( item) ) ;
224+ }
225+ Ok ( None ) => {
226+ return Some ( items) ;
227+ }
228+ Err ( mut e) => {
229+ e. emit ( ) ;
230+ return None ;
231+ }
232+ }
233+ }
234+ }
235+
236+ fn make_impl_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: ImplItem > > {
237+ let mut items = SmallVector :: zero ( ) ;
238+ loop {
239+ match self . parser . parse_impl_item ( ) {
240+ Ok ( mut item) => {
241+ // FIXME better span info.
242+ item. span = self . span ;
243+ items. push ( item) ;
244+
245+ return Some ( items) ;
246+ }
247+ Err ( mut e) => {
248+ e. emit ( ) ;
249+ return None ;
250+ }
251+ }
252+ }
253+ }
254+
255+ fn make_trait_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: TraitItem > > {
256+ let mut items = SmallVector :: zero ( ) ;
257+ loop {
258+ match self . parser . parse_trait_item ( ) {
259+ Ok ( mut item) => {
260+ // FIXME better span info.
261+ item. span = self . span ;
262+ items. push ( item) ;
263+
264+ return Some ( items) ;
265+ }
266+ Err ( mut e) => {
267+ e. emit ( ) ;
268+ return None ;
269+ }
270+ }
271+ }
272+ }
273+
274+ fn make_expr ( mut self : Box < Self > ) -> Option < P < ast:: Expr > > {
275+ match self . parser . parse_expr ( ) {
276+ Ok ( e) => Some ( e) ,
277+ Err ( mut e) => {
278+ e. emit ( ) ;
279+ return None ;
280+ }
281+ }
282+ }
283+
284+ fn make_pat ( mut self : Box < Self > ) -> Option < P < ast:: Pat > > {
285+ match self . parser . parse_pat ( ) {
286+ Ok ( e) => Some ( e) ,
287+ Err ( mut e) => {
288+ e. emit ( ) ;
289+ return None ;
290+ }
291+ }
292+ }
293+
294+ fn make_stmts ( mut self : Box < Self > ) -> Option < SmallVector < ast:: Stmt > > {
295+ let mut stmts = SmallVector :: zero ( ) ;
296+ loop {
297+ if self . parser . token == token:: Eof {
298+ return Some ( stmts) ;
299+ }
300+ match self . parser . parse_full_stmt ( true ) {
301+ Ok ( Some ( mut stmt) ) => {
302+ stmt. span = self . span ;
303+ stmts. push ( stmt) ;
304+ }
305+ Ok ( None ) => { /* continue */ }
306+ Err ( mut e) => {
307+ e. emit ( ) ;
308+ return None ;
309+ }
310+ }
311+ }
312+ }
313+
314+ fn make_ty ( mut self : Box < Self > ) -> Option < P < ast:: Ty > > {
315+ match self . parser . parse_ty ( ) {
316+ Ok ( e) => Some ( e) ,
317+ Err ( mut e) => {
318+ e. emit ( ) ;
319+ return None ;
320+ }
321+ }
322+ }
323+ }
324+
149325/// Represents a thing that maps token trees to Macro Results
150326pub trait TTMacroExpander {
151327 fn expand < ' cx > ( & self ,
@@ -439,24 +615,35 @@ pub enum SyntaxExtension {
439615 /// based upon it.
440616 ///
441617 /// `#[derive(...)]` is a `MultiItemDecorator`.
442- MultiDecorator ( Box < MultiItemDecorator + ' static > ) ,
618+ ///
619+ /// Prefer ProcMacro or MultiModifier since they are more flexible.
620+ MultiDecorator ( Box < MultiItemDecorator > ) ,
443621
444622 /// A syntax extension that is attached to an item and modifies it
445- /// in-place. More flexible version than Modifier.
446- MultiModifier ( Box < MultiItemModifier + ' static > ) ,
623+ /// in-place. Also allows decoration, i.e., creating new items.
624+ MultiModifier ( Box < MultiItemModifier > ) ,
625+
626+ /// A function-like procedural macro. TokenStream -> TokenStream.
627+ ProcMacro ( Box < ProcMacro > ) ,
628+
629+ /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
630+ /// The first TokenSteam is the attribute, the second is the annotated item.
631+ /// Allows modification of the input items and adding new items, similar to
632+ /// MultiModifier, but uses TokenStreams, rather than AST nodes.
633+ AttrProcMacro ( Box < AttrProcMacro > ) ,
447634
448635 /// A normal, function-like syntax extension.
449636 ///
450637 /// `bytes!` is a `NormalTT`.
451638 ///
452639 /// The `bool` dictates whether the contents of the macro can
453640 /// directly use `#[unstable]` things (true == yes).
454- NormalTT ( Box < TTMacroExpander + ' static > , Option < Span > , bool ) ,
641+ NormalTT ( Box < TTMacroExpander > , Option < Span > , bool ) ,
455642
456643 /// A function-like syntax extension that has an extra ident before
457644 /// the block.
458645 ///
459- IdentTT ( Box < IdentMacroExpander + ' static > , Option < Span > , bool ) ,
646+ IdentTT ( Box < IdentMacroExpander > , Option < Span > , bool ) ,
460647}
461648
462649pub type NamedSyntaxExtension = ( Name , SyntaxExtension ) ;
0 commit comments