add recursion to replace! macro.

This commit is contained in:
Tove 2023-05-29 13:02:42 +02:00
parent 3f24c626f7
commit b0bfd103f7
Signed by: TudbuT
GPG key ID: 7D63D5634B7C417F
3 changed files with 28 additions and 15 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "ident_concat"
version = "0.2.3"
version = "0.3.0"
edition = "2021"
repository = "https://github.com/tudbut/ident-concat"
description = "Concatenates identifiers."

View file

@ -3,7 +3,6 @@ extern crate proc_macro;
use proc_macro::{token_stream::IntoIter, *};
fn concat(ts: &mut IntoIter, end: Option<char>) -> Ident {
let mut ident = String::new();
for x in ts {
if let TokenTree::Ident(x) = x {
@ -26,9 +25,27 @@ pub fn ident(ts: TokenStream) -> TokenStream {
TokenStream::from(TokenTree::Ident(concat(&mut ts.into_iter(), None)))
}
fn convert_replace(tt: TokenTree, to_replace: &TokenTree, ident: &Ident) -> TokenTree {
match (&tt, to_replace) {
(TokenTree::Ident(x), TokenTree::Ident(to_replace))
if x.to_string() == to_replace.to_string() =>
{
TokenTree::Ident(ident.clone())
}
(TokenTree::Group(x), _) => TokenTree::Group(Group::new(
x.delimiter(),
TokenStream::from_iter(
x.stream()
.into_iter()
.map(|x| convert_replace(x, to_replace, ident)),
),
)),
_ => tt,
}
}
#[proc_macro]
/// Replaces identifiers with concatenated ones. This will not recurse!
/// Use multiple invocations for recursion.
/// Replaces identifiers with concatenated ones.
/// ```
/// use ident_concat::replace;
/// replace!{ placeholder te st:
@ -42,13 +59,5 @@ pub fn replace(ts: TokenStream) -> TokenStream {
.next()
.expect("syntax: replace!(to_replace with _this: to_replace) => with_this");
let ident = concat(&mut iter, Some(':'));
TokenStream::from_iter(iter.map(|x| {
if matches!((&x, &to_replace), (TokenTree::Ident(x), TokenTree::Ident(to_replace))
if x.to_string() == to_replace.to_string())
{
TokenTree::Ident(ident.clone())
} else {
x
}
}))
TokenStream::from_iter(iter.map(|x| convert_replace(x, &to_replace, &ident)))
}

View file

@ -1,9 +1,13 @@
use ident_concat::*;
fn main() {
let ident!(a b) = 4;
let ident!(a b): u32 = 4;
assert_eq!(ab, ident!(a b));
replace! { placeholder te st:
fn placeholder() -> u32 { 4 }
assert_eq!(test(), 4);
}
replace! { placeholder a b c:
fn placeholder(abc: u32) -> u32 { placeholder }
assert_eq!(ab, abc(ab));
}
assert_eq!(test(), 4);
}