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