blob: b8807d525ae38f2c10a589085b412265e2f8e87e [file] [log] [blame]
David Tolnay18c754c2018-08-21 23:26:58 -04001#![doc(html_root_url = "https://docs.rs/syn-error-experiment/0.0.0")]
2
3extern crate proc_macro2;
4extern crate syn;
5
6#[cfg(feature = "proc-macro")]
7extern crate proc_macro;
8
9#[macro_use]
10pub mod token;
11
12#[macro_use]
13pub mod parse;
14
15#[macro_use]
16mod group;
17
18mod ast;
19mod error;
20mod lookahead;
21
22pub use ast::*;
23pub use proc_macro2::Ident;
24
25// Not public API.
26#[doc(hidden)]
27pub mod export;
28
29use std::str::FromStr;
30
31use proc_macro2::Span;
32use syn::buffer::TokenBuffer;
33
34use parse::{Parse, ParseBuffer, Result};
35
36/// Parse tokens of source code into the chosen syntax tree node.
37#[cfg(feature = "proc-macro")]
38pub fn parse<T: Parse>(input: proc_macro::TokenStream) -> Result<T> {
39 parse2(proc_macro2::TokenStream::from(input))
40}
41
42/// Parse a proc-macro2 token stream into the chosen syntax tree node.
43pub fn parse2<T: Parse>(input: proc_macro2::TokenStream) -> Result<T> {
44 let buf = TokenBuffer::new2(input);
45 let state = ParseBuffer::new(Span::call_site(), buf.begin());
46 T::parse(&state)
47}
48
49/// Parse a string of Rust code into the chosen syntax tree node.
50pub fn parse_str<T: Parse>(input: &str) -> Result<T> {
51 let tokens = proc_macro2::TokenStream::from_str(input)?;
52 parse2(tokens)
53}
54
55/// Parse the input TokenStream of a macro, triggering a compile error if the
56/// tokens fail to parse.
57///
58/// # Intended usage
59///
60/// ```rust
61/// # extern crate proc_macro;
62/// # extern crate syn_error_experiment;
63/// #
64/// use proc_macro::TokenStream;
65/// use syn_error_experiment::parse_macro_input;
66/// use syn_error_experiment::parse::{Parse, ParseStream, Result};
67///
68/// struct MyMacroInput {
69/// /* ... */
70/// }
71///
72/// impl Parse for MyMacroInput {
73/// fn parse(input: ParseStream) -> Result<Self> {
74/// /* ... */
75/// # Ok(MyMacroInput {})
76/// }
77/// }
78///
79/// # const IGNORE: &str = stringify! {
80/// #[proc_macro]
81/// # };
82/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
83/// let input = parse_macro_input!(tokens as MyMacroInput);
84///
85/// /* ... */
86/// # "".parse().unwrap()
87/// }
88/// #
89/// # fn main() {}
90/// ```
91#[cfg(feature = "proc-macro")]
92#[macro_export]
93macro_rules! parse_macro_input {
94 ($tokenstream:ident as $ty:ty) => {
95 match $crate::parse::<$ty>($tokenstream) {
96 $crate::export::Ok(data) => data,
97 $crate::export::Err(err) => {
98 return $crate::export::TokenStream::from(err.into_compile_error());
99 }
100 };
101 };
102}