Delta_Fore
Delta_Fore

Reputation: 3271

Is there a way to achieve an optional expression in a macro?

I have a macro that simplifies the parsing of enums from strings in the form:

enum_printer!(Bar { fun1["AB","CD"]; fun2[] });

To make it slightly easier to use, I would like to make the [] optional i.e. be able to specify

enum_printer!(Bar { fun1["AB","CD"]; fun2; fun3 });

Here's the code as it stands

use failure::Error;
use std::convert::TryFrom;

macro_rules! enum_printer {
    ($name:ident { $($enumeration:ident [$($v:expr),*]);* }) => {
        #[derive(Debug)]
        enum $name {
            $(
                $enumeration,
            )*
        }
        impl<'a> TryFrom<&'a str> for $name {
            type Error = Error;
            fn try_from(value : &'a str) -> Result<$name,Error> {
            match value {
                $(
                    stringify!($enumeration) 
                    $(
                        | $v
                    )*                        
                    => Ok($name::$enumeration),
                )*
                _ => Err(err_msg("Could not convert from string to"))
            }                
            }
        }
    };
}

I've attempted to modify the first line:

($name:ident { $($enumeration:ident [$($v:expr),*]?);* }) => {
error: no rules expected the token `;`
  --> src/main.rs:30:36
   |
30 | enum_printer!(Bar { fun1["AB","CD"]; fun2; fun3 });
   |                                    ^

Is there a way to achieve this?

Upvotes: 5

Views: 1181

Answers (1)

Boiethios
Boiethios

Reputation: 42849

The syntax for the ? is the same as one for * or +: you must surround the optional pattern like this $( <pattern> )?.

Example:

#![feature(macro_at_most_once_rep)]

macro_rules! foo {
    ( $( $e:expr )? ) => {
        $( $e )?
    }
}

In your example, you must write:

($name:ident {
    $(
        $enumeration:ident $(
            [$( $v:expr ),*]
        )? // optional parameter
    );* // possible multiple parameters
}) => {

(I split the line to be clearer)

Upvotes: 4

Related Questions