スポンサーリンク

Rustの手続き型マクロを作成するために使用するsynを普通の用途で使ってみる

RustのsynはRustで書かれたソースコードを解析するためのもので、手続き型マクロを実装するときに重宝するが、普通のプログラムを書く時にも使用できる。

文字列からコードを解析する場合、syn::parse_strを用いる。

ソースコード

fn main() {

// 文字列でRustのコードを書く
    let my_rust_code = "
#[derive(Debug, Clone)]
#[inline]
pub fn myfunc(&self,x:i32, y:i32) -> f32{
  println!(\"Hello, world!\");
}
"
;
    // ソースコードのパース
    let my_parse = syn::parse_str::<syn::ItemFn>(my_rust_code).unwrap();

    let mut myfv:MyFnVisitor = MyFnVisitor{indent:0};
    myfv.visit_item_fn(&my_parse);

}
/////////////////////////////
/// 以下、解析のための構造体並びに関数

struct MyFnVisitor{
    indent:usize,
}

use quote::ToTokens;
use syn::visit::Visit;

impl<'a> syn::visit::Visit<'a> for MyFnVisitor{

    // 関数をパースするには、visit_item_fnを実装する
    fn visit_item_fn(&mut self, node: &'a syn::ItemFn) {

        let mut indentstr:String = "".to_string();
        for _ in 0..self.indent{
            indentstr.push_str(" ");
        }

        println!("{}****************",indentstr);

        // 関数がパブリックかどうかをチェック
        if let syn::Visibility::Public(_pub) = node.vis {
            println!("{}pub? {}",indentstr,_pub.to_token_stream().to_string());
        }

        // アトリビュートを取得
        for attr in &node.attrs{
            let id = attr.path().get_ident().unwrap();
            println!("{}attribute: {}",indentstr,id);
        }

        // 関数名を取得
        let function_name = &node.sig.ident;
        println!("{}func_name: {}",indentstr,function_name);

        // 引数を取得
        for arg in node.sig.inputs.iter(){
            match arg{

                syn::FnArg::Typed(pat_type) => {                    

                    if let syn::Pat::Ident(patident) = &*pat_type.pat{
                        let arg_name = &patident.ident;
                        let arg_type = &pat_type.ty.to_token_stream().to_string();
                        println!("{}arg: {} {}",indentstr,
                            &arg_name,
                            &arg_type
                        );
                    }
                }
                _ => {}
            }
        }

    }

}

Cargo.toml

[dependencies]
syn = {version = "2.0", features = ["full","visit"] }
quote = "1.0.33"

実行結果

****************
pub? pub
attribute: derive
attribute: inline
func_name: myfunc
arg: x i32
arg: y i32

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: