Export derive macro from my lib

I write a crate (library) for lexical code analyzer. In general, my program works like this: it receives input text and gives the corresponding tokens. I want a user of the library to create own custom enum/struct of token, not me as the library author.

For example:

enum Token {
    Star, // *
    Plus, // +
    Space,
}

To make it work into analyzer, the enum/struct needs implement the ReadToken trait.
This is a trait that allows you to convert text to the corresponding token.

pub trait ReadToken<'t> {
    type Token;
    fn read_token(&self, text: &'t str) -> Self::Token;
}

This trait is also impl by functions. For example, so that you can specify the function of converting text to token and use it to tokenize.

Since the implementation of the trait for the token is trivial I decided to make it possible to derive automatically like:

#[derive(Clone, ReadToken)] // it also requires clone
enum Token {
    Star, // *
    Plus, // +
    Space,
}

I wrote the following implementation for deriving in extern crate read-token-derive:


extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

#[proc_macro_derive(ReadToken)]
pub fn read_token(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();

    let gen = if ast.generics.lifetimes.is_empty() {
        impl_read_token(&ast)
    } else {
        impl_read_token_lifetime(&ast)
    };

    gen.parse().unwrap()
}

fn impl_read_token_lifetime(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    quote! {
        impl ReadToken<'static> for #name<'static> {
            type Token = #name<'static>;

            fn read_token(&self, _: &str) -> Self::Token {
                self.clone()
            }
        }
    }
}

fn impl_read_token(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    quote! {
        impl ReadToken<'static> for #name {
            type Token = #name;

            fn read_token(&self, _: &str) -> Self::Token {
                self.clone()
            }
        }
    }
}

I tested this in the library and it works. But I don't know how to export this from the library to use deriving from the outside.

Simply reexport it as you would any other function. pub use {crate_name}::read_token should work, AFAIK.

1 Like

I can't export read_token function, but I tried:

pub use read_token_derive::ReadToken;

As suggested by the compiler.
And it looks like it was exported.
Thanks for help!

Right, sorry - I was thinking about attribute/functional proc macros, not derives. Happy to see it worked, anyway!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.