1+ //! # nom-parse-trait
2+ //!
3+ //! This macro generates a `ParseFrom` implementation for a struct or enum using the provided
4+ //! nom expression(s). The expression should return a tuple for the parsed fields.
5+ //!
6+ //! There are 2 separate macros available, [`parse_from()`] and [`parse_match()`].
7+ //! The first one is really generic and can be useful in many cases, since you have the full
8+ //! flexibility of nom functions and combinators. The second one is a very simple one that
9+ //! matches a string verbatim. This is useful when you have a very simple format that you want
10+ //! to parse.
11+ //!
12+ //! # nom functions
13+ //!
14+ //! The expression in the `parse_from` attribute will be translated to be using valid nom functions.
15+ //! The main function here is to automatically put the namespace before the function name, so you
16+ //! don't need a ton of use statements in your code. But there are also a couple of special cases:
17+ //!
18+ //! - `{}` or `()` will be replaced with a [`nom_parse_trait::ParseFrom::parse`] call for the
19+ //! corresponding field. This is useful when you are using types that have implemented the
20+ //! `ParseFrom` trait already.
21+ //! - Strings, bytes strings and characters will be translated to match the input verbatim using
22+ //! the [`nom::bytes::complete::tag`] function.
23+ //!
24+ //! # Input types that are supported
25+ //!
26+ //! The generated `ParseFrom` implementation is made to be very generic, where it supports any
27+ //! input and error type from nom. This is done with a where clause with many traits that the input
28+ //! should have implemented. All of these are true for the standard `&str` and `&[u8]` types.
29+ //!
30+ //! If you run into a situation where the trait limitations on the input type does not match your
31+ //! use case, please open an issue on the GitHub repository.
32+ //!
33+ //! # Known limitations
34+ //!
35+ //! - When your try to use a custom parser combinator, the nom function parser will try to change
36+ //! all parameters to be nom parsers. This is useful in many cases, but when you need to pass in
37+ //! a normal string for example, it won't work. In these cases, you can define a separate function
38+ //! to wrap the call. I'm not sure how to fix that right now, but I'm open to suggestions.
39+ //!
40+ //! - Since the generated input type is very generic, all functions that you want to use in the
41+ //! nom expression should also be very generic. In the future I might add a way to specify if you
42+ //! want to generate a specific input type, but for now it's not possible.
43+
144extern crate proc_macro;
245mod fields;
346mod nom_packages;
@@ -16,6 +59,63 @@ use syn::{
1659 LitStr , TypeParam , WhereClause , WherePredicate ,
1760} ;
1861
62+ /// This macro generates a [`nom_parse_trait::ParseFrom`] implementation for a struct or enum using
63+ /// the provided nom expression(s). The expression should return a tuple for the parsed fields.
64+ ///
65+ /// # Examples
66+ ///
67+ /// ## Basic struct with fields
68+ ///
69+ /// This first example shows how to parse a simple struct with two fields, using the `separated_pair`
70+ /// combinator. Here we also show some of the special parsing that goes on behind the scenes, where
71+ /// the special {} syntax means that it infers the type parser it needs to use in that place. Also,
72+ /// we accept normal strings as matching input, which will be translated to `tag` function calls.
73+ ///
74+ /// ```rust
75+ /// use nom_parse_macros::parse_from;
76+ ///
77+ /// #[parse_from(separated_pair({}, tuple(space0, ",", space0), {}))]
78+ /// struct NumberPair {
79+ /// x: u32,
80+ /// y: u32,
81+ /// }
82+ /// ```
83+ ///
84+ /// ## Basic enum with variants
85+ ///
86+ /// This example shows how we can define a format for each variant in an enum. The first variant
87+ /// actually uses the default `ParseFrom` implementation for parsing the u32. The `Numbers` variant
88+ /// uses a custom format, which is a delimited list of u32 values.
89+ ///
90+ /// ```rust
91+ /// use nom_parse_macros::parse_from;
92+ ///
93+ /// #[parse_from]
94+ /// enum MultipleTypes {
95+ /// Number(u32),
96+ /// #[format(delimited('(', separated_list0(",", {}), ')'))]
97+ /// Numbers(Vec<u32>),
98+ /// }
99+ /// ```
100+ ///
101+ /// ## Derived fields
102+ ///
103+ /// Sometimes it's useful to have a field that is not actually parsed, but derived from the other
104+ /// fields. This can be done with the `#[derived]` attribute. In this example, we derive the sum of
105+ /// the two fields `x` and `y`.
106+ ///
107+ /// ```rust
108+ /// use nom_parse_macros::parse_from;
109+ ///
110+ /// #[parse_from(separated_pair({}, tuple(space0, ",", space0), {}))]
111+ /// struct NumberPair {
112+ /// x: u32,
113+ /// y: u32,
114+ /// #[derived(x + y)]
115+ /// sum: u32,
116+ /// }
117+ /// ```
118+
19119#[ proc_macro_attribute]
20120pub fn parse_from ( attrs : TokenStream , object : TokenStream ) -> TokenStream {
21121 match parse_macro_input ! ( object as Item ) {
@@ -135,6 +235,27 @@ fn generate_enum_parser(mut object: ItemEnum) -> TokenStream {
135235 )
136236}
137237
238+ /// The `parse_match` macro can be used to match strings verbatim. This is useful when you have
239+ /// a very simple format that you want to parse. The {} gets replaced with a parser for the
240+ /// corresponding field. The rest of the characters are matched verbatim.
241+ ///
242+ /// # Example
243+ ///
244+ /// This example shows how to parse a three-dimensional vector from a string with a fixed format.
245+ /// As you can see, this macro is limited in its use, but is very straightforward to use in cases
246+ /// where it works.
247+ ///
248+ /// ```rust
249+ /// use nom_parse_macros::parse_match;
250+ ///
251+ /// #[parse_match("({},{},{})")]
252+ /// struct Vector3 {
253+ /// x: u32,
254+ /// y: u32,
255+ /// z: u32,
256+ /// }
257+ /// ```
258+ ///
138259#[ proc_macro_attribute]
139260pub fn parse_match ( attrs : TokenStream , object : TokenStream ) -> TokenStream {
140261 let literal = parse_macro_input ! { attrs as LitStr } ;
0 commit comments