// The macro invocation in the previous test case contained an empty loop body
// inside the braces. In reality we want for the macro to accept arbitrary
// tokens inside the braces.
//
// The caller should be free to write whatever they want inside the braces. The
// seq macro won't care whether they write a statement, or a function, or a
// struct, or whatever else. So we will work with the loop body as a TokenStream
// rather than as a syntax tree.
//
// Before moving on, ensure that your implementation knows what has been written
// inside the curly braces as a value of type TokenStream.
//
//
// Resources:
//
// - Explanation of the purpose of proc-macro2:
// https://docs.rs/proc-macro2/1.0/proc_macro2/
use seq::seq;
macro_rules! expand_to_nothing {
($arg:literal) => {
// nothing
};
}
seq!(N in 0..4 {
expand_to_nothing!(N);
});
fn main() {}
這一關我們主要解析的是整個資料的結構。
因為對於N in 0..4
並不是標準的語法,我們要解析並且操作,返回符合的標準語法。
impl syn::parse::Parse for crate::parser::SeqParser {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let variable_ident = input.parse::<syn::Ident>()?;
let _ = input.parse::<syn::Token!(in)>()?;
let begin = input.parse::<syn::LitInt>()?.base10_parse()?;
let _ = input.parse::<syn::Token!(..)>()?;
let end = input.parse::<syn::LitInt>()?.base10_parse()?;
let body_buf;
let _ = syn::braced!(body_buf in input);
let body = body_buf.parse::<proc_macro2::TokenStream>()?;
syn::Result::Ok(crate::parser::SeqParser {
variable_ident,
begin,
end,
body,
})
}
}
比較值的一提的有三點
- 透過
parse
方法,我們可以自動解析自己想要的資料型別 - 使用
syn::Token(?)
我們可以匹配指定的token
syn::braced!
可以抽取{}
中的資料,然後慢慢解析
按照前面所述的每個token
,我們逐漸的解析了每一個資料。
當然,因為想要支援syn::parse_macro_input!
,結構體解析的時候必須要實現syn:: parse::Parse
。所以主幹的題解可以改成這樣了。
#[proc_macro]
pub fn seq(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let _ = syn::parse_macro_input!(input as crate::parser::SeqParser);
proc_macro2::TokenStream::new().into
}
目前而言,已經支援parse_macro_input!
了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結