1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use syn::{
    parse::{discouraged::Speculative, Parse, ParseStream},
    token::Token,
};

pub trait Validate {
    fn validate(stream: &ParseStream) -> bool;
}

impl<T> Validate for T
where
    T: Token,
{
    fn validate(stream: &ParseStream) -> bool {
        T::peek(stream.cursor())
    }
}

pub trait SpeculativeValidate: Parse {
    fn speculative_validate(stream: &ParseStream) -> Option<Self> {
        let fork = stream.fork();

        match Self::parse(&fork) {
            Ok(parsed) => {
                stream.advance_to(&fork);
                Some(parsed)
            }
            Err(_) => None,
        }
    }
}

impl<T> SpeculativeValidate for T where T: Parse {}

#[macro_export]
macro_rules! try_parse {
    ($input:expr => $ty:ty) => {{
        use syn::parse::discouraged::Speculative;

        let fork = $input.fork();

        match <$ty>::parse(&fork) {
            Ok(parsed) => {
                $input.advance_to(&fork);
                Some(parsed)
            }
            Err(_) => None,
        }
    }};
}