Implement Ident::parse_any as an extension trait
diff --git a/src/error.rs b/src/error.rs
index 619af10..6673aa3 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -22,7 +22,7 @@
/// An error with a default error message.
///
/// NOTE: We should provide better error messages in the future.
-pub fn parse_error<O>() -> PResult<'static, O> {
+pub fn parse_error<'a, O>() -> PResult<'a, O> {
Err(ParseError(None))
}
diff --git a/src/parsers.rs b/src/parsers.rs
index bdd0c6a..8be5dde 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -95,6 +95,8 @@
#[macro_export]
macro_rules! call {
($i:expr, $fun:expr $(, $args:expr)*) => {{
+ #[allow(unused_imports)]
+ use $crate::synom::ext::*;
let i = $i;
eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
let r = $fun(i $(, $args)*);
@@ -143,9 +145,11 @@
#[cfg(not(synom_verbose_trace))]
#[macro_export]
macro_rules! call {
- ($i:expr, $fun:expr $(, $args:expr)*) => {
+ ($i:expr, $fun:expr $(, $args:expr)*) => {{
+ #[allow(unused_imports)]
+ use $crate::synom::ext::*;
$fun($i $(, $args)*)
- };
+ }};
}
/// Transform the result of a parser by applying a function or closure.
diff --git a/src/synom.rs b/src/synom.rs
index 5f0bf78..28444f3 100644
--- a/src/synom.rs
+++ b/src/synom.rs
@@ -296,3 +296,61 @@
}
}
}
+
+/// Extension traits that are made available within the `call!` parser.
+///
+/// *This module is available if Syn is built with the `"parsing"` feature.*
+pub mod ext {
+ use super::*;
+ use proc_macro2::Ident;
+
+ /// Additional parsing methods for `Ident`.
+ ///
+ /// This trait is sealed and cannot be implemented for types outside of Syn.
+ ///
+ /// *This trait is available if Syn is built with the `"parsing"` feature.*
+ pub trait IdentExt: Sized + private::Sealed {
+ /// Parses any identifier including keywords.
+ ///
+ /// This is useful when parsing a DSL which allows Rust keywords as
+ /// identifiers.
+ ///
+ /// ```rust
+ /// #[macro_use]
+ /// extern crate syn;
+ ///
+ /// use syn::Ident;
+ ///
+ /// // Parses input that looks like `name = NAME` where `NAME` can be
+ /// // any identifier.
+ /// //
+ /// // Examples:
+ /// //
+ /// // name = anything
+ /// // name = impl
+ /// named!(parse_dsl -> Ident, do_parse!(
+ /// custom_keyword!(name) >>
+ /// punct!(=) >>
+ /// name: call!(Ident::parse_any) >>
+ /// (name)
+ /// ));
+ /// #
+ /// # fn main() {}
+ /// ```
+ fn parse_any(input: Cursor) -> PResult<Self>;
+ }
+
+ impl IdentExt for Ident {
+ fn parse_any(input: Cursor) -> PResult<Self> {
+ input.ident().map_or_else(parse_error, Ok)
+ }
+ }
+
+ mod private {
+ use proc_macro2::Ident;
+
+ pub trait Sealed {}
+
+ impl Sealed for Ident {}
+ }
+}