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
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#![doc(html_root_url = "https://docs.rs/syn-error-experiment/0.0.0")]

extern crate proc_macro2;
extern crate syn;

#[cfg(feature = "proc-macro")]
extern crate proc_macro;

#[macro_use]
pub mod token;

#[macro_use]
pub mod parse;

#[macro_use]
mod group;

mod ast;
mod error;
mod lookahead;

pub use ast::*;
pub use proc_macro2::Ident;

// Not public API.
#[doc(hidden)]
pub mod export;

use std::str::FromStr;

use proc_macro2::Span;
use syn::buffer::TokenBuffer;

use parse::{Parse, ParseBuffer, Result};

/// Parse tokens of source code into the chosen syntax tree node.
#[cfg(feature = "proc-macro")]
pub fn parse<T: Parse>(input: proc_macro::TokenStream) -> Result<T> {
    parse2(proc_macro2::TokenStream::from(input))
}

/// Parse a proc-macro2 token stream into the chosen syntax tree node.
pub fn parse2<T: Parse>(input: proc_macro2::TokenStream) -> Result<T> {
    let buf = TokenBuffer::new2(input);
    let state = ParseBuffer::new(Span::call_site(), buf.begin());
    T::parse(&state)
}

/// Parse a string of Rust code into the chosen syntax tree node.
pub fn parse_str<T: Parse>(input: &str) -> Result<T> {
    let tokens = proc_macro2::TokenStream::from_str(input)?;
    parse2(tokens)
}

/// Parse the input TokenStream of a macro, triggering a compile error if the
/// tokens fail to parse.
///
/// # Intended usage
///
/// ```rust
/// # extern crate proc_macro;
/// # extern crate syn_error_experiment;
/// #
/// use proc_macro::TokenStream;
/// use syn_error_experiment::parse_macro_input;
/// use syn_error_experiment::parse::{Parse, ParseStream, Result};
///
/// struct MyMacroInput {
///     /* ... */
/// }
///
/// impl Parse for MyMacroInput {
///     fn parse(input: ParseStream) -> Result<Self> {
///         /* ... */
/// #       Ok(MyMacroInput {})
///     }
/// }
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro]
/// # };
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(tokens as MyMacroInput);
///
///     /* ... */
/// #   "".parse().unwrap()
/// }
/// #
/// # fn main() {}
/// ```
#[cfg(feature = "proc-macro")]
#[macro_export]
macro_rules! parse_macro_input {
    ($tokenstream:ident as $ty:ty) => {
        match $crate::parse::<$ty>($tokenstream) {
            $crate::export::Ok(data) => data,
            $crate::export::Err(err) => {
                return $crate::export::TokenStream::from(err.into_compile_error());
            }
        };
    };
}