Expansion de constantes en français
Nous souhaitons créer une macro procédurale french
qui remplacera un nombre litéral (une constante) par sa représentation textuelle en français lors de la compilation. Par exemple, le code suivant
println!("1000 + 230 = {}", french!(1230));
affichera
1000 + 230 = mille-deux-cent-trente (1230)
Nous nous aiderons pour cela de l'excellent crate french-numbers
.
-
Ajoutez le crate
french-numbers
aux dépendances du projetmacros
. Notons que nous ne l'ajouterons pas aux dépendances du projetpwdchk
car tout se passera lors de la compilation. -
Créez dans
src/lib.rs
du projetmacros
une fonctionfrench
avec l'attribut#[proc_macro]
avec la signature correspondant à une macro procédurale :
extern crate proc_macro;
#[proc_macro]
pub fn french(item: TokenStream) -> TokenStream {
item
}
Étant donné que proc_macro
est fourni par le compilateur et pas ajouté explicitement dans nos dépendances, il faut l'importer avec extern crate proc_macro
.
Pour l'instant, notre macro ne fait rien. Nous pouvons le vérifier en important macros::french
dans notre programme pwdchk
et en recopiant le println!()
ci-dessus dans notre programme principal.
Il faut maintenant remplir notre fonction french
. En vous aidant des exemples du cours, effectuez les étapes suivantes :
- Parsez le flux d'entrée sous la forme d'un
LitInt
qui représente un entier litéral grâce à la macro idione qui vient du cratesyn
. - Parsez cet entier litéral, et en cas de succès, construisez la chaîne de caractères contenant sa représentation en français suivi de sa valeur entre parenthèses. Vous pouvez ensuite construire un
proc_macro2::TokenStream
en utilisant la macroquote
du crate éponyme et le convertir enproc_macro::TokenStream
avecinto()
. - En cas d'erreur lors de l'étape précédente, insérez avec la macro
quote_spanned
du cratequote
une invocation de la macrocompile_error
expliquant que la macrofrench
ne fonctionne qu'avec un entier litéral.
Bravo, vous avez créé votre première macro procédurale. Vérifiez qu'elle fonctionne comme attendu.