@@ -9,7 +9,7 @@ import syntax::visit::*;
9
9
import syntax:: ext:: base:: * ;
10
10
import syntax:: ext:: build:: * ;
11
11
import syntax:: parse:: parser;
12
- import syntax:: parse:: parser:: { parse_from_source_str} ;
12
+ import syntax:: parse:: parser:: { parser , parse_from_source_str} ;
13
13
14
14
import syntax:: print:: * ;
15
15
import std:: io:: * ;
@@ -19,12 +19,53 @@ import codemap::span;
19
19
type aq_ctxt = @{ lo : uint ,
20
20
mutable gather: [ { lo : uint , hi : uint , e : @ast:: expr } ] } ;
21
21
22
- fn gather_anti_quotes ( lo : uint , e : @ast:: expr ) -> aq_ctxt
22
+ iface qq_helper {
23
+ fn span( ) -> span;
24
+ fn visit ( aq_ctxt , vt < aq_ctxt > ) ;
25
+ fn mk_parse_fn ( ext_ctxt , span ) -> @ast:: expr ;
26
+ }
27
+ impl of qq_helper for @ast:: expr {
28
+ fn span ( ) -> span { self . span }
29
+ fn visit ( cx : aq_ctxt , v : vt < aq_ctxt > ) { visit_expr ( self , cx, v) ; }
30
+ fn mk_parse_fn ( cx : ext_ctxt , sp : span ) -> @ast:: expr {
31
+ mk_path ( cx, sp, [ "syntax" , "parse" , "parser" , "parse_expr" ] )
32
+ }
33
+ }
34
+ impl of qq_helper for @ast:: ty {
35
+ fn span ( ) -> span { self . span }
36
+ fn visit ( cx : aq_ctxt , v : vt < aq_ctxt > ) { visit_ty ( self , cx, v) ; }
37
+ fn mk_parse_fn ( cx : ext_ctxt , sp : span ) -> @ast:: expr {
38
+ mk_path ( cx, sp, [ "syntax" , "ext" , "qquote" , "parse_ty" ] )
39
+ }
40
+ }
41
+ impl of qq_helper for @ast:: item {
42
+ fn span ( ) -> span { self . span }
43
+ fn visit ( cx : aq_ctxt , v : vt < aq_ctxt > ) { visit_item ( self , cx, v) ; }
44
+ fn mk_parse_fn ( cx : ext_ctxt , sp : span ) -> @ast:: expr {
45
+ mk_path ( cx, sp, [ "syntax" , "ext" , "qquote" , "parse_item" ] )
46
+ }
47
+ }
48
+ impl of qq_helper for @ast:: stmt {
49
+ fn span ( ) -> span { self . span }
50
+ fn visit ( cx : aq_ctxt , v : vt < aq_ctxt > ) { visit_stmt ( self , cx, v) ; }
51
+ fn mk_parse_fn ( cx : ext_ctxt , sp : span ) -> @ast:: expr {
52
+ mk_path ( cx, sp, [ "syntax" , "ext" , "qquote" , "parse_stmt" ] )
53
+ }
54
+ }
55
+ impl of qq_helper for @ast:: pat {
56
+ fn span ( ) -> span { self . span }
57
+ fn visit ( cx : aq_ctxt , v : vt < aq_ctxt > ) { visit_pat ( self , cx, v) ; }
58
+ fn mk_parse_fn ( cx : ext_ctxt , sp : span ) -> @ast:: expr {
59
+ mk_path ( cx, sp, [ "syntax" , "parse" , "parser" , "parse_pat" ] )
60
+ }
61
+ }
62
+
63
+ fn gather_anti_quotes < N : qq_helper > ( lo : uint , node : N ) -> aq_ctxt
23
64
{
24
65
let v = @{ visit_expr: visit_expr_aq
25
66
with * default_visitor ( ) } ;
26
67
let cx = @{ lo: lo, mutable gather: [ ] } ;
27
- visit_expr_aq ( e , cx, mk_vt ( v) ) ;
68
+ node . visit ( cx, mk_vt ( v) ) ;
28
69
ret cx;
29
70
}
30
71
@@ -43,31 +84,78 @@ fn is_space(c: char) -> bool {
43
84
syntax:: parse:: lexer:: is_whitespace ( c)
44
85
}
45
86
46
- fn expand_ast ( ecx : ext_ctxt , _sp : span , _arg :
47
- ast:: mac_arg , body : ast:: mac_body )
87
+ fn expand_ast ( ecx : ext_ctxt , _sp : span ,
88
+ arg : ast:: mac_arg , body : ast:: mac_body )
48
89
-> @ast:: expr
49
90
{
91
+ let what = "expr" ;
92
+ option:: may ( arg) { |arg|
93
+ let args: [ @ast:: expr] =
94
+ alt arg. node {
95
+ ast:: expr_vec ( elts, _) { elts }
96
+ _ {
97
+ ecx. span_fatal
98
+ ( _sp, "#ast requires arguments of the form `[...]`." )
99
+ }
100
+ } ;
101
+ if vec:: len :: < @ast:: expr > ( args) != 1 u {
102
+ ecx. span_fatal ( _sp, "#ast requires exactly one arg" ) ;
103
+ }
104
+ alt ( args[ 0 ] . node ) {
105
+ ast:: expr_path ( @{ node : { idents : id, _} , _} ) if vec:: len ( id) == 1 u
106
+ { what = id[ 0 ] }
107
+ _ { ecx. span_fatal ( args[ 0 ] . span , "expected an identifier" ) ; }
108
+ }
109
+ }
50
110
let body = get_mac_body ( ecx, _sp, body) ;
51
- let cm = ecx. session ( ) . parse_sess . cm ;
52
- let str = @codemap:: span_to_snippet ( body. span , cm) ;
53
- let ( fname, ss) = codemap:: get_substr_info ( cm,
54
- body. span . lo , body. span . hi ) ;
55
- let { node: e , _} = parse_from_source_str ( parser:: parse_expr,
56
- fname, some ( ss) , str,
57
- ecx. session ( ) . opts . cfg ,
58
- ecx. session ( ) . parse_sess ) ;
59
- ret expand_qquote ( ecx, e. span , some ( * str) , e) ;
60
- }
61
-
62
- fn expand_qquote ( ecx : ext_ctxt , sp : span , maybe_str : option:: t < str > ,
63
- e : @ast:: expr )
111
+ fn finish < T : qq_helper > ( ecx : ext_ctxt , body : ast:: mac_body_ ,
112
+ f : fn ( p : parser ) -> T )
113
+ -> @ast:: expr
114
+ {
115
+ let cm = ecx. session ( ) . parse_sess . cm ;
116
+ let str = @codemap:: span_to_snippet ( body. span , cm) ;
117
+ let ( fname, ss) = codemap:: get_substr_info
118
+ ( cm, body. span . lo , body. span . hi ) ;
119
+ let node = parse_from_source_str
120
+ ( f, fname, some ( ss) , str,
121
+ ecx. session ( ) . opts . cfg , ecx. session ( ) . parse_sess ) ;
122
+ ret expand_qquote ( ecx, node. span ( ) , some ( * str) , node) ;
123
+ }
124
+
125
+ ret alt what {
126
+ "expr" { finish ( ecx, body, parser:: parse_expr) }
127
+ "ty" { finish ( ecx, body, parse_ty) }
128
+ "item" { finish ( ecx, body, parse_item) }
129
+ "stmt" { finish ( ecx, body, parse_stmt) }
130
+ "pat" { finish ( ecx, body, parser:: parse_pat) }
131
+ _ { ecx. span_fatal ( _sp, "unsupported ast type" ) }
132
+ } ;
133
+ }
134
+
135
+ fn parse_ty ( p : parser ) -> @ast:: ty {
136
+ parser:: parse_ty ( p, false )
137
+ }
138
+
139
+ fn parse_stmt ( p : parser ) -> @ast:: stmt {
140
+ parser:: parse_stmt ( p, [ ] )
141
+ }
142
+
143
+ fn parse_item ( p : parser ) -> @ast:: item {
144
+ alt ( parser:: parse_item ( p, [ ] ) ) {
145
+ some ( item) { item}
146
+ none { fail; /* FIXME: Error message, somehow */ }
147
+ }
148
+ }
149
+
150
+ fn expand_qquote < N : qq_helper >
151
+ ( ecx : ext_ctxt , sp : span , maybe_str : option:: t < str > , node : N )
64
152
-> @ast:: expr
65
153
{
66
154
let str = alt ( maybe_str) {
67
155
some ( s) { s}
68
156
none { codemap : : span_to_snippet ( sp, ecx. session ( ) . parse_sess . cm ) }
69
157
} ;
70
- let qcx = gather_anti_quotes ( sp. lo , e ) ;
158
+ let qcx = gather_anti_quotes ( sp. lo , node ) ;
71
159
let cx = qcx;
72
160
let prev = 0 u;
73
161
for { lo: lo, _} in cx. gather {
@@ -107,8 +195,10 @@ fn expand_qquote(ecx: ext_ctxt, sp: span, maybe_str: option::t<str>,
107
195
[ ] ) ;
108
196
let pcall = mk_call ( cx, sp,
109
197
[ "syntax" , "parse" , "parser" ,
110
- "parse_expr_from_source_str" ] ,
111
- [ mk_str ( cx, sp, "<anon>" ) ,
198
+ "parse_from_source_str" ] ,
199
+ [ node. mk_parse_fn ( cx, sp) ,
200
+ mk_str ( cx, sp, "<anon>" ) ,
201
+ mk_path ( cx, sp, [ "option" , "none" ] ) ,
112
202
mk_unary ( cx, sp, ast:: box ( ast:: imm) ,
113
203
mk_str ( cx, sp, str2) ) ,
114
204
mk_access_ ( cx, sp,
0 commit comments