@@ -59,6 +59,11 @@ struct Context<'a, 'b> {
59
59
next_arg : uint ,
60
60
}
61
61
62
+ pub enum Invocation {
63
+ Call ( @ast:: Expr ) ,
64
+ MethodCall ( @ast:: Expr , ast:: Ident ) ,
65
+ }
66
+
62
67
/// Parses the arguments from the given list of tokens, returning None
63
68
/// if there's a parse error so we can continue parsing other format!
64
69
/// expressions.
@@ -67,8 +72,9 @@ struct Context<'a, 'b> {
67
72
///
68
73
/// Some((fmtstr, unnamed arguments, ordering of named arguments,
69
74
/// named arguments))
70
- fn parse_args ( ecx : & mut ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
71
- -> ( @ast:: Expr , Option < ( @ast:: Expr , Vec < @ast:: Expr > , Vec < StrBuf > ,
75
+ fn parse_args ( ecx : & mut ExtCtxt , sp : Span , allow_method : bool ,
76
+ tts : & [ ast:: TokenTree ] )
77
+ -> ( Invocation , Option < ( @ast:: Expr , Vec < @ast:: Expr > , Vec < StrBuf > ,
72
78
HashMap < StrBuf , @ast:: Expr > ) > ) {
73
79
let mut args = Vec :: new ( ) ;
74
80
let mut names = HashMap :: < StrBuf , @ast:: Expr > :: new ( ) ;
@@ -80,22 +86,31 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
80
86
. map ( |x| ( * x) . clone ( ) )
81
87
. collect ( ) ) ;
82
88
// Parse the leading function expression (maybe a block, maybe a path)
83
- let extra = p. parse_expr ( ) ;
89
+ let invocation = if allow_method {
90
+ let e = p. parse_expr ( ) ;
91
+ if !p. eat ( & token:: COMMA ) {
92
+ ecx. span_err ( sp, "expected token: `,`" ) ;
93
+ return ( Call ( e) , None ) ;
94
+ }
95
+ MethodCall ( e, p. parse_ident ( ) )
96
+ } else {
97
+ Call ( p. parse_expr ( ) )
98
+ } ;
84
99
if !p. eat ( & token:: COMMA ) {
85
100
ecx. span_err ( sp, "expected token: `,`" ) ;
86
- return ( extra , None ) ;
101
+ return ( invocation , None ) ;
87
102
}
88
103
89
104
if p. token == token:: EOF {
90
105
ecx. span_err ( sp, "requires at least a format string argument" ) ;
91
- return ( extra , None ) ;
106
+ return ( invocation , None ) ;
92
107
}
93
108
let fmtstr = p. parse_expr ( ) ;
94
109
let mut named = false ;
95
110
while p. token != token:: EOF {
96
111
if !p. eat ( & token:: COMMA ) {
97
112
ecx. span_err ( sp, "expected token: `,`" ) ;
98
- return ( extra , None ) ;
113
+ return ( invocation , None ) ;
99
114
}
100
115
if p. token == token:: EOF { break } // accept trailing commas
101
116
if named || ( token:: is_ident ( & p. token ) &&
@@ -110,13 +125,13 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
110
125
ecx. span_err ( p. span ,
111
126
"expected ident, positional arguments \
112
127
cannot follow named arguments") ;
113
- return ( extra , None ) ;
128
+ return ( invocation , None ) ;
114
129
}
115
130
_ => {
116
131
ecx. span_err ( p. span ,
117
132
format ! ( "expected ident for named argument, but found `{}`" ,
118
133
p. this_token_to_str( ) ) ) ;
119
- return ( extra , None ) ;
134
+ return ( invocation , None ) ;
120
135
}
121
136
} ;
122
137
let interned_name = token:: get_ident ( ident) ;
@@ -137,7 +152,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
137
152
args. push ( p. parse_expr ( ) ) ;
138
153
}
139
154
}
140
- return ( extra , Some ( ( fmtstr, args, order, names) ) ) ;
155
+ return ( invocation , Some ( ( fmtstr, args, order, names) ) ) ;
141
156
}
142
157
143
158
impl < ' a , ' b > Context < ' a , ' b > {
@@ -595,7 +610,7 @@ impl<'a, 'b> Context<'a, 'b> {
595
610
596
611
/// Actually builds the expression which the iformat! block will be expanded
597
612
/// to
598
- fn to_expr ( & self , extra : @ast :: Expr ) -> @ast:: Expr {
613
+ fn to_expr ( & self , invocation : Invocation ) -> @ast:: Expr {
599
614
let mut lets = Vec :: new ( ) ;
600
615
let mut locals = Vec :: new ( ) ;
601
616
let mut names = Vec :: from_fn ( self . name_positions . len ( ) , |_| None ) ;
@@ -699,8 +714,16 @@ impl<'a, 'b> Context<'a, 'b> {
699
714
let resname = self . ecx . ident_of ( "__args" ) ;
700
715
lets. push ( self . ecx . stmt_let ( self . fmtsp , false , resname, result) ) ;
701
716
let res = self . ecx . expr_ident ( self . fmtsp , resname) ;
702
- let result = self . ecx . expr_call ( extra. span , extra, vec ! (
703
- self . ecx. expr_addr_of( extra. span, res) ) ) ;
717
+ let result = match invocation {
718
+ Call ( e) => {
719
+ self . ecx . expr_call ( e. span , e,
720
+ vec ! ( self . ecx. expr_addr_of( e. span, res) ) )
721
+ }
722
+ MethodCall ( e, m) => {
723
+ self . ecx . expr_method_call ( e. span , e, m,
724
+ vec ! ( self . ecx. expr_addr_of( e. span, res) ) )
725
+ }
726
+ } ;
704
727
let body = self . ecx . expr_block ( self . ecx . block ( self . fmtsp , lets,
705
728
Some ( result) ) ) ;
706
729
@@ -794,13 +817,25 @@ impl<'a, 'b> Context<'a, 'b> {
794
817
}
795
818
}
796
819
797
- pub fn expand_args ( ecx : & mut ExtCtxt , sp : Span ,
798
- tts : & [ ast:: TokenTree ] ) -> Box < base:: MacResult > {
820
+ pub fn expand_format_args ( ecx : & mut ExtCtxt , sp : Span ,
821
+ tts : & [ ast:: TokenTree ] ) -> Box < base:: MacResult > {
822
+
823
+ match parse_args ( ecx, sp, false , tts) {
824
+ ( invocation, Some ( ( efmt, args, order, names) ) ) => {
825
+ MacExpr :: new ( expand_preparsed_format_args ( ecx, sp, invocation, efmt,
826
+ args, order, names) )
827
+ }
828
+ ( _, None ) => MacExpr :: new ( ecx. expr_uint ( sp, 2 ) )
829
+ }
830
+ }
831
+
832
+ pub fn expand_format_args_method ( ecx : & mut ExtCtxt , sp : Span ,
833
+ tts : & [ ast:: TokenTree ] ) -> Box < base:: MacResult > {
799
834
800
- match parse_args ( ecx, sp, tts) {
801
- ( extra , Some ( ( efmt, args, order, names) ) ) => {
802
- MacExpr :: new ( expand_preparsed_format_args ( ecx, sp, extra , efmt, args ,
803
- order, names) )
835
+ match parse_args ( ecx, sp, true , tts) {
836
+ ( invocation , Some ( ( efmt, args, order, names) ) ) => {
837
+ MacExpr :: new ( expand_preparsed_format_args ( ecx, sp, invocation , efmt,
838
+ args , order, names) )
804
839
}
805
840
( _, None ) => MacExpr :: new ( ecx. expr_uint ( sp, 2 ) )
806
841
}
@@ -810,7 +845,7 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span,
810
845
/// name=names...)` and construct the appropriate formatting
811
846
/// expression.
812
847
pub fn expand_preparsed_format_args ( ecx : & mut ExtCtxt , sp : Span ,
813
- extra : @ast :: Expr ,
848
+ invocation : Invocation ,
814
849
efmt : @ast:: Expr , args : Vec < @ast:: Expr > ,
815
850
name_ordering : Vec < StrBuf > ,
816
851
names : HashMap < StrBuf , @ast:: Expr > ) -> @ast:: Expr {
@@ -869,5 +904,5 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
869
904
}
870
905
}
871
906
872
- cx. to_expr ( extra )
907
+ cx. to_expr ( invocation )
873
908
}
0 commit comments