cam*_*rcu 1 rust rust-proc-macros
我正在摆弄 Rust 的过程宏,我想制作一个自定义的有趣属性,将 TokenStream 中的所有字符串文字转换为 SHOUTING CASE。
到目前为止,我的 proc-macro 库中的内容如下amplify:
// lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, File};
#[proc_macro_attribute]
pub fn amplify(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as File);
// TODO: modify string literals (LitStr) in token tree to be upper case
let quoted = quote! {#input};
println!("{:#?}", quoted); // just print at compile time to see what is produced
quoted.into()
}
Run Code Online (Sandbox Code Playgroud)
当应用于简单的 hello-world 程序时,它应该变成“Hello, World!” 字符串文字转换为“HELLO, WORLD!” 在编译时。例子:
use amplify::amplify;
#[amplify]
pub fn main() {
println!("Hello, World!");
}
Run Code Online (Sandbox Code Playgroud)
然后运行代码:
cargo run
# prints: HELLO, WORLD!
Run Code Online (Sandbox Code Playgroud)
检查二进制文件中的字符串:
strings target/debug/hello-world | grep -i hello
# prints: HELLO, WORLD! (and possibly other string garbage from the binary)
Run Code Online (Sandbox Code Playgroud)
需要注意的是,我希望属性宏递归地遍历标记树以查找所有字符串文字。我不知道如何检查树中的每个项目是否是字符串文字,或者项目是否需要递归。
任何帮助将不胜感激!
我没有太多使用 的经验proc_macro,但基于这个答案,我发现很容易对其进行调整以手动替换令牌树中的文字,而无需使用syn或quote板条箱。这种方法涉及使用litrscrate 来分离文字的类型。
use proc_macro::{TokenStream, TokenTree, Literal};
use litrs::StringLit;
fn replace_uppercase(item: TokenStream) -> TokenStream {
item.into_iter()
.map(|x| {
match x {
TokenTree::Group(group) => {
// Pass items in group back through replace_uppercase
let new_group = Group::new(group.deliminer(), replace_uppercase(group.stream()));
TokenTree::Group(new_group)
},
TokenTree::Literal(literal) => {
// The `litrs` crate was an easy and straightforward approach, so I used it to determine the type of input literals
if let Ok(input_string) = StringLit::try_from(literal) {
// Convert string literals with uppercase versions
TokenTree::Literal(Literal::string(input_string.value().to_uppercase()))
} else {
TokenTree::Literal(literal)
}
},
v => v,
}
})
.collect()
}
#[proc_macro_attribute]
pub fn amplify(_attr: TokenStream, item: TokenStream) -> TokenStream {
replace_uppercase(item)
}
Run Code Online (Sandbox Code Playgroud)
老实说,syn这可能是更正确的选择,但是我发现很难阅读文档,因为该界面主要由宏组成。
| 归档时间: |
|
| 查看次数: |
1481 次 |
| 最近记录: |