Есть ли способ получить необязательное выражение в макросе? - PullRequest
0 голосов
/ 06 июня 2018

У меня есть макрос, который упрощает разбор перечислений из строк в виде:

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

Чтобы сделать его немного проще, я хотел бы сделать [] необязательным, т.е. иметь возможностьукажите

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

Вот код в его нынешнем виде

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"))
            }                
            }
        }
    };
}

Я попытался изменить первую строку:

($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 });
   |                                    ^

Есть лиспособ достичь этого?

1 Ответ

0 голосов
/ 06 июня 2018

Синтаксис для ? совпадает с синтаксисом для * или +: вы должны окружить необязательный шаблон следующим образом $( <pattern> )?.

Пример:

#![feature(macro_at_most_once_rep)]

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

В вашем примере вы должны написать:

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

(я разбил строку для большей ясности)

...