3
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
5
5
use quote:: { ToTokens , Tokens } ;
6
- use super :: visit:: { Visitor , RecursiveVisitor } ;
7
6
use std:: fs:: File ;
8
7
use std:: io:: { Read , Write } ;
9
- use std:: mem;
10
8
use std:: path:: Path ;
11
9
use std:: vec;
12
10
use std:: iter;
@@ -15,42 +13,69 @@ use syn;
15
13
pub fn expand ( from : & Path , to : & Path ) {
16
14
let mut source = String :: new ( ) ;
17
15
File :: open ( from) . unwrap ( ) . read_to_string ( & mut source) . unwrap ( ) ;
18
- let mut crate_ = syn:: parse_crate ( & source) . expect ( "Parsing rules.rs module" ) ;
19
- let mut visitor = ExpanderVisitor ;
20
-
21
- RecursiveVisitor { node_visitor : & mut visitor } . visit_crate ( & mut crate_) ;
22
-
16
+ let tts = syn:: parse_token_trees ( & source) . expect ( "Parsing rules.rs module" ) ;
23
17
let mut tokens = Tokens :: new ( ) ;
24
- crate_. to_tokens ( & mut tokens) ;
18
+ tokens. append_all ( expand_tts ( tts) ) ;
19
+
25
20
let code = tokens. to_string ( ) . replace ( "{ " , "{\n " ) . replace ( " }" , "\n }" ) ;
26
21
File :: create ( to) . unwrap ( ) . write_all ( code. as_bytes ( ) ) . unwrap ( ) ;
27
22
}
28
23
29
- struct ExpanderVisitor ;
24
+ fn expand_tts ( tts : Vec < syn:: TokenTree > ) -> Vec < syn:: TokenTree > {
25
+ use syn:: * ;
26
+ let mut expanded = Vec :: new ( ) ;
27
+ let mut tts = tts. into_iter ( ) ;
28
+ while let Some ( tt) = tts. next ( ) {
29
+ match tt {
30
+ TokenTree :: Token ( Token :: Ident ( ident) ) => {
31
+ if ident != "match_byte" {
32
+ expanded. push ( TokenTree :: Token ( Token :: Ident ( ident) ) ) ;
33
+ continue ;
34
+ }
30
35
31
- impl Visitor for ExpanderVisitor {
32
- fn visit_expression ( & mut self , expr : & mut syn:: Expr ) {
33
- let tokens = match expr. node {
34
- syn:: ExprKind :: Mac ( ref mut macro_) if macro_. path == syn:: Path :: from ( "match_byte" ) => {
35
- mem:: replace ( & mut macro_. tts , vec ! [ ] )
36
- }
37
- _ => return ,
38
- } ;
39
- let ( to_be_matched, table, cases, wildcard_binding) = parse_match_bytes_macro ( tokens) ;
40
- * expr = expand_match_bytes_macro ( to_be_matched, & table, cases, wildcard_binding) ;
41
- }
36
+ match tts. next ( ) {
37
+ Some ( TokenTree :: Token ( Token :: Not ) ) => { } ,
38
+ other => {
39
+ expanded. push ( TokenTree :: Token ( Token :: Ident ( ident) ) ) ;
40
+ if let Some ( other) = other {
41
+ expanded. push ( other) ;
42
+ }
43
+ continue ;
44
+ }
45
+ }
42
46
43
- fn visit_statement ( & mut self , stmt : & mut syn:: Stmt ) {
44
- let tokens = match * stmt {
45
- syn:: Stmt :: Mac ( ref mut macro_) if macro_. 0 . path == syn:: Path :: from ( "match_byte" ) => {
46
- mem:: replace ( & mut macro_. 0 . tts , vec ! [ ] )
47
+ let tts = match tts. next ( ) {
48
+ Some ( TokenTree :: Delimited ( Delimited { tts, .. } ) ) => tts,
49
+ other => {
50
+ expanded. push ( TokenTree :: Token ( Token :: Ident ( ident) ) ) ;
51
+ expanded. push ( TokenTree :: Token ( Token :: Not ) ) ;
52
+ if let Some ( other) = other {
53
+ expanded. push ( other) ;
54
+ }
55
+ continue ;
56
+ }
57
+ } ;
58
+
59
+ let ( to_be_matched, table, cases, wildcard_binding) = parse_match_bytes_macro ( tts) ;
60
+ let expr = expand_match_bytes_macro ( to_be_matched,
61
+ & table,
62
+ cases,
63
+ wildcard_binding) ;
64
+
65
+ let tts = syn:: parse_token_trees ( & expr)
66
+ . expect ( "parsing macro expansion as token trees" ) ;
67
+ expanded. extend ( expand_tts ( tts) ) ;
47
68
}
48
- _ => return ,
49
- } ;
50
- let ( to_be_matched, table, cases, wildcard_binding) = parse_match_bytes_macro ( tokens) ;
51
- let expr = expand_match_bytes_macro ( to_be_matched, & table, cases, wildcard_binding) ;
52
- * stmt = syn:: Stmt :: Expr ( Box :: new ( expr) ) ;
69
+ TokenTree :: Delimited ( Delimited { delim, tts } ) => {
70
+ expanded. push ( TokenTree :: Delimited ( Delimited {
71
+ delim : delim,
72
+ tts : expand_tts ( tts) ,
73
+ } ) )
74
+ }
75
+ other => expanded. push ( other) ,
76
+ }
53
77
}
78
+ expanded
54
79
}
55
80
56
81
/// Parses a token tree corresponding to the `match_byte` macro.
@@ -80,18 +105,7 @@ impl Visitor for ExpanderVisitor {
80
105
/// this case).
81
106
///
82
107
fn parse_match_bytes_macro ( tts : Vec < syn:: TokenTree > ) -> ( Vec < syn:: TokenTree > , [ u8 ; 256 ] , Vec < Case > , Option < syn:: Ident > ) {
83
- use syn:: TokenTree :: Delimited ;
84
- use syn:: DelimToken :: Brace ;
85
-
86
108
let mut tts = tts. into_iter ( ) ;
87
- let inner_tts = match tts. next ( ) {
88
- Some ( Delimited ( syn:: Delimited { delim : Brace , tts } ) ) => tts,
89
- other => panic ! ( "expected one top-level {{}} block, got: {:?}" , other) ,
90
- } ;
91
-
92
- assert_eq ! ( tts. next( ) , None ) ;
93
-
94
- let mut tts = inner_tts. into_iter ( ) ;
95
109
96
110
// Grab the thing we're matching, until we find a comma.
97
111
let mut left_hand_side = vec ! [ ] ;
@@ -204,7 +218,7 @@ fn expand_match_bytes_macro(to_be_matched: Vec<syn::TokenTree>,
204
218
table : & [ u8 ; 256 ] ,
205
219
cases : Vec < Case > ,
206
220
binding : Option < syn:: Ident > )
207
- -> syn :: Expr {
221
+ -> String {
208
222
use std:: fmt:: Write ;
209
223
210
224
assert ! ( !to_be_matched. is_empty( ) ) ;
@@ -253,5 +267,5 @@ fn expand_match_bytes_macro(to_be_matched: Vec<syn::TokenTree>,
253
267
254
268
expr. push_str ( "}\n " ) ; // top
255
269
256
- syn :: parse_expr ( & expr) . expect ( "couldn't parse expression?" )
270
+ expr
257
271
}
0 commit comments