gpt4 book ai didi

rust - 如何在程序宏中获取文字的值和类型?

转载 作者:行者123 更新时间:2023-12-03 11:23:55 25 4
gpt4 key购买 nike

我正在实现一个类似函数的程序宏,它将单个字符串文字作为参数,但我不知道如何获取字符串文字的值。
如果我打印变量,它会显示一堆字段,其中包括类型和值。他们显然就在那里,在某个地方。我如何获得它们?

extern crate proc_macro;
use proc_macro::{TokenStream,TokenTree};

#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
let input: Vec<TokenTree> = input.into_iter().collect();
let literal = match &input.get(0) {
Some(TokenTree::Literal(literal)) => literal,
_ => panic!()
};

// can't do anything with "literal"
// println!("{:?}", literal.lit.symbol); says "unknown field"

format!("{:?}", format!("{:?}", literal)).parse().unwrap()
}
#![feature(proc_macro_hygiene)]
extern crate macros;

fn main() {
let value = macros::my_macro!("hahaha");
println!("it is {}", value);
// prints "it is Literal { lit: Lit { kind: Str, symbol: "hahaha", suffix: None }, span: Span { lo: BytePos(100), hi: BytePos(108), ctxt: #0 } }"
}

最佳答案

在无数次遇到同样的问题之后,我终于写了一个库来帮助解决这个问题: litrs on crates.io .它的编译速度比 syn 快并让您检查文字。

use std::convert::TryFrom;
use litrs::StringLit;
use proc_macro::TokenStream;
use quote::quote;


#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
let input = input.into_iter().collect::<Vec<_>>();
if input.len() != 1 {
let msg = format!("expected exactly one input token, got {}", input.len());
return quote! { compile_error!(#msg) }.into();
}

let string_lit = match StringLit::try_from(&input[0]) {
// Error if the token is not a string literal
Err(e) => return e.to_compile_error(),
Ok(lit) => lit,
};

// `StringLit::value` returns the actual string value represented by the
// literal. Quotes are removed and escape sequences replaced with the
// corresponding value.
let v = string_lit.value();

// TODO: implement your logic here
}
the documentation of litrs 想要查询更多的信息。

要获取有关文字的更多信息, litrs使用 Display Literal 的实现获得一个字符串表示(就像它在源代码中编写的那样),然后解析该字符串。例如,如果字符串以 0x 开头人们知道它必须是一个整数文字,如果它以 r#" 开头人们知道它是一个原始字符串文字。 crate syn完全一样。
当然,考虑到 rustc 已经解析了文字,编写和运行第二个解析器似乎有点浪费。是的,这很不幸,而且在 proc_literal 中有更好的 API会更可取。但现在,我想 litrs (或 syn,如果您正在使用 syn)是最好的解决方案。

(PS:我通常不喜欢在 Stack Overflow 上推广自己的库,但我非常熟悉 OP 遇到的问题,我非常认为 litrs 是目前最适合这项工作的工具。)

关于rust - 如何在程序宏中获取文字的值和类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61169932/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com