33 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 
44
55use  quote:: { ToTokens ,  Tokens } ; 
6- use  super :: visit:: { Visitor ,  RecursiveVisitor } ; 
76use  std:: fs:: File ; 
87use  std:: io:: { Read ,  Write } ; 
9- use  std:: mem; 
108use  std:: path:: Path ; 
119use  std:: vec; 
1210use  std:: iter; 
@@ -15,42 +13,69 @@ use syn;
1513pub  fn  expand ( from :  & Path ,  to :  & Path )  { 
1614    let  mut  source = String :: new ( ) ; 
1715    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" ) ; 
2317    let  mut  tokens = Tokens :: new ( ) ; 
24-     crate_. to_tokens ( & mut  tokens) ; 
18+     tokens. append_all ( expand_tts ( tts) ) ; 
19+ 
2520    let  code = tokens. to_string ( ) . replace ( "{ " ,  "{\n " ) . replace ( " }" ,  "\n }" ) ; 
2621    File :: create ( to) . unwrap ( ) . write_all ( code. as_bytes ( ) ) . unwrap ( ) ; 
2722} 
2823
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+                 } 
3035
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+                 } 
4246
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) ) ; 
4768            } 
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+         } 
5377    } 
78+     expanded
5479} 
5580
5681/// Parses a token tree corresponding to the `match_byte` macro. 
@@ -80,18 +105,7 @@ impl Visitor for ExpanderVisitor {
80105///    this case). 
81106/// 
82107fn  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- 
86108    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 ( ) ; 
95109
96110    // Grab the thing we're matching, until we find a comma. 
97111    let  mut  left_hand_side = vec ! [ ] ; 
@@ -204,7 +218,7 @@ fn expand_match_bytes_macro(to_be_matched: Vec<syn::TokenTree>,
204218                            table :  & [ u8 ;  256 ] , 
205219                            cases :  Vec < Case > , 
206220                            binding :  Option < syn:: Ident > ) 
207-                             -> syn :: Expr  { 
221+                             -> String  { 
208222    use  std:: fmt:: Write ; 
209223
210224    assert ! ( !to_be_matched. is_empty( ) ) ; 
@@ -253,5 +267,5 @@ fn expand_match_bytes_macro(to_be_matched: Vec<syn::TokenTree>,
253267
254268    expr. push_str ( "}\n " ) ;  // top 
255269
256-     syn :: parse_expr ( & expr) . expect ( "couldn't parse expression?" ) 
270+     expr
257271} 
0 commit comments