syn,quote

quote

This crate provides the quote! macro for turning Rust syntax tree data structures into tokens of source code. The idea of quasi-quoting is that we write code that we treat as data.

基本类型

#![allow(unused)]
fn main() {
    let u = 12usize;
    let i = -38i32;
    let f = 3.1415926f64;
    let c = '\r';
    let s = "\r\nhello\tworld\r\n";

    assert_eq!(
        "12usize - 38i32 3.1415926f64 '\\r' \"\\r\\nhello\\tworld\\r\\n\"",
        quote! {
          u #i #f #c #s
        }
        .to_string()
    );
    macro_rules! m {
        ($literal:literal) => {
            quote!($literal)
        };
    }

    let expected = "- false";
    assert_eq!(expected, m!(-false).to_string());
}

重复、循环

#![allow(unused)]
fn main() {
    let f0 = format_ident!("World");
    let f1 = format_ident!("Hello{x}", x = f0);
    assert_eq!("HelloWorld",f1.to_string());
    // ident not impl f64
    let f2 = format_ident!("Hello{x}", x = 4050usize);

    assert_eq!("Hello4050",f2.to_string());
    let num: u32 = 10;

    let octal = format_ident!("Id_{:o}", num);
    assert_eq!(octal, "Id_12");

    let binary = format_ident!("Id_{:b}", num);
    assert_eq!(binary, "Id_1010");

    let lower_hex = format_ident!("Id_{:x}", num);
    assert_eq!(lower_hex, "Id_a");

    let upper_hex = format_ident!("Id_{:X}", num);
    assert_eq!(upper_hex, "Id_A");

}

注释

#![allow(unused)]

fn main() {
  let token1 = quote!{
    /* comment */
  };
  let token2 = quote!{
    // comment 
  };

  assert_eq!(token1.to_string(),token2.to_string())

}

syn

Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code.

syn::File

#![allow(unused)]
fn main() {
    let mut file = File::open(&filename).expect("Unable to open file");

    let mut src = String::new();
    file.read_to_string(&mut src).expect("Unable to read file");

    let ast = syn::parse_file(&src).unwrap();
    if let Some(shebang) = ast.shebang {
        println!("{}", shebang);
    }
    println!("{} items", ast.items.len());
}

DeriveInput for proc_macro_derive

#![allow(unused)]
fn main() {
#[proc_macro_derive(HeapSize)]
pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // Parse the input tokens into a syntax tree.
    let input = parse_macro_input!(input as DeriveInput);

    // Used in the quasi-quotation below as `#name`.
    let name = input.ident;

    // Add a bound `T: HeapSize` to every type parameter T.
    let generics = add_trait_bounds(input.generics);
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    // Generate an expression to sum up the heap size of each field.
    let sum = heap_size_sum(&input.data);

    let expanded = quote! {
        // The generated impl.
        ...
    };

    // Hand the output tokens back to the compiler.
    proc_macro::TokenStream::from(expanded)
}

}

fold 可以在语法转换时hook

#![allow(unused)]
fn main() {
impl Fold for Args {
    // 处理expr类型时
    fn fold_expr(&mut self, e: Expr) -> Expr {
        match e {
            Expr::Assign(e) => {
                if self.should_print_expr(&e.left) {
                    self.assign_and_print(*e.left, &e.eq_token, *e.right)
                } else {
                    Expr::Assign(fold::fold_expr_assign(self, e))
                }
            }
            Expr::Binary(e) if is_assign_op(e.op) => {
                if self.should_print_expr(&e.left) {
                    self.assign_and_print(*e.left, &e.op, *e.right)
                } else {
                    Expr::Binary(fold::fold_expr_binary(self, e))
                }
            }
            _ => fold::fold_expr(self, e),
        }
    }
    // 处理stmt类型
    fn fold_stmt(&mut self, s: Stmt) -> Stmt {
        match s {
            Stmt::Local(s) => {
                if s.init.is_some() && self.should_print_pat(&s.pat) {
                    self.let_and_print(s)
                } else {
                    Stmt::Local(fold::fold_local(self, s))
                }
            }
            _ => fold::fold_stmt(self, s),
        }
    }
}


}