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