Syn 获取平面令牌流
Syn get flat token stream
为了这个例子:我想写一个 proc 宏属性来修改函数体中的所有数字文字。
我有 syn::Block
来自 syn::FnItem
。我想映射块中的所有标记并更改文字。我目前有:
let token_stream = func
.block
.to_token_stream()
.into_iter()
.map(|token| ...)
func.block = Box::new(syn::parse2::<Block>(token_stream.collect()).unwrap());
问题是 to_token_stream
来自 Quote::ToTokens
returns 一个 proc_macro2::TokenStream
并且它的 into_iter
项目是 proc_macro2::TokenTree
这是一个嵌套表示代币。
所以对于代表 2 + (3 + 4)
的块
迭代器遍历以下单个项目:
Group {
delimiter: Brace,
stream: TokenStream [
Literal {
kind: Integer,
symbol: "2",
suffix: None,
span: #0 bytes(209..210),
},
Punct {
ch: '+',
spacing: Alone,
span: #0 bytes(211..212),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Literal {
kind: Integer,
symbol: "3",
suffix: None,
span: #0 bytes(214..215),
},
Punct {
ch: '+',
spacing: Alone,
span: #0 bytes(216..217),
},
Literal {
kind: Integer,
symbol: "4",
suffix: None,
span: #0 bytes(218..219),
},
],
span: #0 bytes(213..220),
},
],
span: #0 bytes(203..222),
}
令牌在结构中深度嵌套的位置。
我需要一个如下所示的平面表示:
Literal("2")
Plus
ParenthesisOpen
Literal("3")
Plus
Literal("4")
ParenthesisClose
这可能吗?我可以在 map
之前编写自己的 flat_map
thinh 以使其工作,但这需要大量工作。 syn 会公开任何东西吗?也许我不应该在进行转换之前将其解析为 syn::Block
...?
原来syn有一个mutable visiting module。您可以像这样使用递归访问者,而不是接触令牌流:
use syn::{visit_mut::{self, VisitMut}, LitInt};
struct MyNumberLiteralModifier;
impl VisitMut for MyNumberLiteralModifier {
fn visit_lit_int_mut(&mut self, node: &mut LitInt) {
*node = LitInt::new("10", node.span());
}
}
MyNumberLiteralModifier.walk_block(&mut my_block);
为此必须为 syn
启用 "visit-mut"
功能
为了这个例子:我想写一个 proc 宏属性来修改函数体中的所有数字文字。
我有 syn::Block
来自 syn::FnItem
。我想映射块中的所有标记并更改文字。我目前有:
let token_stream = func
.block
.to_token_stream()
.into_iter()
.map(|token| ...)
func.block = Box::new(syn::parse2::<Block>(token_stream.collect()).unwrap());
问题是 to_token_stream
来自 Quote::ToTokens
returns 一个 proc_macro2::TokenStream
并且它的 into_iter
项目是 proc_macro2::TokenTree
这是一个嵌套表示代币。
所以对于代表 2 + (3 + 4)
迭代器遍历以下单个项目:
Group {
delimiter: Brace,
stream: TokenStream [
Literal {
kind: Integer,
symbol: "2",
suffix: None,
span: #0 bytes(209..210),
},
Punct {
ch: '+',
spacing: Alone,
span: #0 bytes(211..212),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Literal {
kind: Integer,
symbol: "3",
suffix: None,
span: #0 bytes(214..215),
},
Punct {
ch: '+',
spacing: Alone,
span: #0 bytes(216..217),
},
Literal {
kind: Integer,
symbol: "4",
suffix: None,
span: #0 bytes(218..219),
},
],
span: #0 bytes(213..220),
},
],
span: #0 bytes(203..222),
}
令牌在结构中深度嵌套的位置。
我需要一个如下所示的平面表示:
Literal("2")
Plus
ParenthesisOpen
Literal("3")
Plus
Literal("4")
ParenthesisClose
这可能吗?我可以在 map
之前编写自己的 flat_map
thinh 以使其工作,但这需要大量工作。 syn 会公开任何东西吗?也许我不应该在进行转换之前将其解析为 syn::Block
...?
原来syn有一个mutable visiting module。您可以像这样使用递归访问者,而不是接触令牌流:
use syn::{visit_mut::{self, VisitMut}, LitInt};
struct MyNumberLiteralModifier;
impl VisitMut for MyNumberLiteralModifier {
fn visit_lit_int_mut(&mut self, node: &mut LitInt) {
*node = LitInt::new("10", node.span());
}
}
MyNumberLiteralModifier.walk_block(&mut my_block);
为此必须为 syn
启用"visit-mut"
功能