]>
git.proxmox.com Git - rustc.git/blob - vendor/synom/src/lib.rs
1 //! Adapted from [`nom`](https://github.com/Geal/nom) by removing the
2 //! `IResult::Incomplete` variant which:
5 //! - is an unintuitive footgun when working with non-streaming use cases, and
6 //! - more than doubles compilation time.
8 //! ## Whitespace handling strategy
10 //! As (sy)nom is a parser combinator library, the parsers provided here and
11 //! that you implement yourself are all made up of successively more primitive
12 //! parsers, eventually culminating in a small number of fundamental parsers
13 //! that are implemented in Rust. Among these are `punct!` and `keyword!`.
15 //! All synom fundamental parsers (those not combined out of other parsers)
16 //! should be written to skip over leading whitespace in their input. This way,
17 //! as long as every parser eventually boils down to some combination of
18 //! fundamental parsers, we get correct whitespace handling at all levels for
21 //! For our use case, this strategy is a huge improvement in usability,
22 //! correctness, and compile time over nom's `ws!` strategy.
24 extern crate unicode_xid
;
32 /// The result of a parser.
33 #[derive(Debug, PartialEq, Eq, Clone)]
34 pub enum IResult
<I
, O
> {
35 /// Parsing succeeded. The first field contains the rest of the unparsed
36 /// data and the second field contains the parse result.
42 impl<'a
, O
> IResult
<&'a
str, O
> {
43 /// Unwraps the result, asserting the the parse is complete. Panics with a
44 /// message based on the given string if the parse failed or is incomplete.
48 /// #[macro_use] extern crate synom;
51 /// use syn::parse::ty;
53 /// // One or more Rust types separated by commas.
54 /// named!(comma_separated_types -> Vec<Ty>,
55 /// separated_nonempty_list!(punct!(","), ty)
59 /// let input = "&str, Map<K, V>, String";
61 /// let parsed = comma_separated_types(input).expect("comma-separated types");
63 /// assert_eq!(parsed.len(), 3);
64 /// println!("{:?}", parsed);
67 pub fn expect(self, name
: &str) -> O
{
69 IResult
::Done(mut rest
, o
) => {
70 rest
= space
::skip_whitespace(rest
);
74 panic
!("unparsed tokens after {}: {:?}", name
, rest
)
77 IResult
::Error
=> panic
!("failed to parse {}", name
),
82 /// Define a function from a parser combination.
84 /// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
87 /// # extern crate syn;
88 /// # #[macro_use] extern crate synom;
90 /// # use syn::parse::ty;
91 /// // One or more Rust types separated by commas.
92 /// named!(pub comma_separated_types -> Vec<Ty>,
93 /// separated_nonempty_list!(punct!(","), ty)
99 ($name
:ident
-> $o
:ty
, $submac
:ident
!( $
($args
:tt
)* )) => {
100 fn $
name(i
: &str) -> $
crate::IResult
<&str, $o
> {
101 $submac
!(i
, $
($args
)*)
105 (pub $name
:ident
-> $o
:ty
, $submac
:ident
!( $
($args
:tt
)* )) => {
106 pub fn $
name(i
: &str) -> $
crate::IResult
<&str, $o
> {
107 $submac
!(i
, $
($args
)*)
112 /// Invoke the given parser function with the passed in arguments.
114 /// - **Syntax:** `call!(FUNCTION, ARGS...)`
116 /// where the signature of the function is `fn(&str, ARGS...) -> IResult<&str, T>`
117 /// - **Output:** `T`, the result of invoking the function `FUNCTION`
120 /// #[macro_use] extern crate synom;
122 /// use synom::IResult;
124 /// // Parses any string up to but not including the given character, returning
125 /// // the content up to the given character. The given character is required to
126 /// // be present in the input string.
127 /// fn skip_until(input: &str, ch: char) -> IResult<&str, &str> {
128 /// if let Some(pos) = input.find(ch) {
129 /// IResult::Done(&input[pos..], &input[..pos])
135 /// // Parses any string surrounded by tilde characters '~'. Returns the content
136 /// // between the tilde characters.
137 /// named!(surrounded_by_tilde -> &str, delimited!(
139 /// call!(skip_until, '~'),
144 /// let input = "~ abc def ~";
146 /// let inner = surrounded_by_tilde(input).expect("surrounded by tilde");
148 /// println!("{:?}", inner);
153 ($i
:expr
, $fun
:expr $
(, $args
:expr
)*) => {
158 /// Transform the result of a parser by applying a function or closure.
160 /// - **Syntax:** `map!(THING, FN)`
161 /// - **Output:** the return type of function FN applied to THING
164 /// extern crate syn;
165 /// #[macro_use] extern crate synom;
167 /// use syn::{Item, Ident};
168 /// use syn::parse::item;
170 /// fn get_item_ident(item: Item) -> Ident {
174 /// // Parses an item and returns the name (identifier) of the item only.
175 /// named!(item_ident -> Ident,
176 /// map!(item, get_item_ident)
179 /// // Or equivalently:
180 /// named!(item_ident2 -> Ident,
181 /// map!(item, |i: Item| i.ident)
185 /// let input = "fn foo() {}";
187 /// let parsed = item_ident(input).expect("item");
189 /// assert_eq!(parsed, "foo");
194 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $g
:expr
) => {
195 match $submac
!($i
, $
($args
)*) {
196 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
197 $
crate::IResult
::Done(i
, o
) => {
198 $
crate::IResult
::Done(i
, call
!(o
, $g
))
203 ($i
:expr
, $f
:expr
, $g
:expr
) => {
204 map
!($i
, call
!($f
), $g
)
208 /// Parses successfully if the given parser fails to parse. Does not consume any
211 /// - **Syntax:** `not!(THING)`
212 /// - **Output:** `()`
215 /// extern crate syn;
216 /// #[macro_use] extern crate synom;
217 /// use synom::IResult;
219 /// // Parses a shebang line like `#!/bin/bash` and returns the part after `#!`.
220 /// // Note that a line starting with `#![` is an inner attribute, not a
222 /// named!(shebang -> &str, preceded!(
223 /// tuple!(tag!("#!"), not!(tag!("["))),
224 /// take_until!("\n")
228 /// let bin_bash = "#!/bin/bash\n";
229 /// let parsed = shebang(bin_bash).expect("shebang");
230 /// assert_eq!(parsed, "/bin/bash");
232 /// let inner_attr = "#![feature(specialization)]\n";
233 /// let err = shebang(inner_attr);
234 /// assert_eq!(err, IResult::Error);
239 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
240 match $submac
!($i
, $
($args
)*) {
241 $
crate::IResult
::Done(_
, _
) => $
crate::IResult
::Error
,
242 $
crate::IResult
::Error
=> $
crate::IResult
::Done($i
, ()),
247 /// Conditionally execute the given parser.
249 /// If you are familiar with nom, this is nom's `cond_with_error` parser.
251 /// - **Syntax:** `cond!(CONDITION, THING)`
252 /// - **Output:** `Some(THING)` if the condition is true, else `None`
255 /// extern crate syn;
256 /// #[macro_use] extern crate synom;
258 /// use syn::parse::boolean;
260 /// // Parses a tuple of booleans like `(true, false, false)`, possibly with a
261 /// // dotdot indicating omitted values like `(true, true, .., true)`. Returns
262 /// // separate vectors for the booleans before and after the dotdot. The second
263 /// // vector is None if there was no dotdot.
264 /// named!(bools_with_dotdot -> (Vec<bool>, Option<Vec<bool>>), do_parse!(
266 /// before: separated_list!(punct!(","), boolean) >>
267 /// after: option!(do_parse!(
268 /// // Only allow comma if there are elements before dotdot, i.e. cannot
269 /// // be `(, .., true)`.
270 /// cond!(!before.is_empty(), punct!(",")) >>
272 /// after: many0!(preceded!(punct!(","), boolean)) >>
273 /// // Only allow trailing comma if there are elements after dotdot,
274 /// // i.e. cannot be `(true, .., )`.
275 /// cond!(!after.is_empty(), option!(punct!(","))) >>
278 /// // Allow trailing comma if there is no dotdot but there are elements.
279 /// cond!(!before.is_empty() && after.is_none(), option!(punct!(","))) >>
285 /// let input = "(true, false, false)";
286 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
287 /// assert_eq!(parsed, (vec![true, false, false], None));
289 /// let input = "(true, true, .., true)";
290 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
291 /// assert_eq!(parsed, (vec![true, true], Some(vec![true])));
293 /// let input = "(.., true)";
294 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
295 /// assert_eq!(parsed, (vec![], Some(vec![true])));
297 /// let input = "(true, true, ..)";
298 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
299 /// assert_eq!(parsed, (vec![true, true], Some(vec![])));
301 /// let input = "(..)";
302 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
303 /// assert_eq!(parsed, (vec![], Some(vec![])));
308 ($i
:expr
, $cond
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
310 match $submac
!($i
, $
($args
)*) {
311 $
crate::IResult
::Done(i
, o
) => $
crate::IResult
::Done(i
, ::std
::option
::Option
::Some(o
)),
312 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
315 $
crate::IResult
::Done($i
, ::std
::option
::Option
::None
)
319 ($i
:expr
, $cond
:expr
, $f
:expr
) => {
320 cond
!($i
, $cond
, call
!($f
))
324 /// Fail to parse if condition is false, otherwise parse the given parser.
326 /// This is typically used inside of `option!` or `alt!`.
328 /// - **Syntax:** `cond_reduce!(CONDITION, THING)`
329 /// - **Output:** `THING`
332 /// extern crate syn;
333 /// #[macro_use] extern crate synom;
335 /// use syn::parse::boolean;
337 /// #[derive(Debug, PartialEq)]
338 /// struct VariadicBools {
343 /// // Parse one or more comma-separated booleans, possibly ending in "..." to
344 /// // indicate there may be more.
345 /// named!(variadic_bools -> VariadicBools, do_parse!(
346 /// data: separated_nonempty_list!(punct!(","), boolean) >>
347 /// trailing_comma: option!(punct!(",")) >>
348 /// // Only allow "..." if there is a comma after the last boolean. Using
349 /// // `cond_reduce!` is more convenient here than using `cond!`. The
350 /// // alternatives are:
352 /// // - `cond!(c, option!(p))` or `option!(cond!(c, p))`
353 /// // Gives `Some(Some("..."))` for variadic and `Some(None)` or `None`
354 /// // which both mean not variadic.
355 /// // - `cond_reduce!(c, option!(p))`
356 /// // Incorrect; would fail to parse if there is no trailing comma.
357 /// // - `option!(cond_reduce!(c, p))`
358 /// // Gives `Some("...")` for variadic and `None` otherwise. Perfect!
359 /// variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
362 /// variadic: variadic.is_some(),
367 /// let input = "true, true";
368 /// let parsed = variadic_bools(input).expect("variadic bools");
369 /// assert_eq!(parsed, VariadicBools {
370 /// data: vec![true, true],
374 /// let input = "true, ...";
375 /// let parsed = variadic_bools(input).expect("variadic bools");
376 /// assert_eq!(parsed, VariadicBools {
377 /// data: vec![true],
383 macro_rules
! cond_reduce
{
384 ($i
:expr
, $cond
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
386 $submac
!($i
, $
($args
)*)
388 $
crate::IResult
::Error
392 ($i
:expr
, $cond
:expr
, $f
:expr
) => {
393 cond_reduce
!($i
, $cond
, call
!($f
))
397 /// Parse two things, returning the value of the second.
399 /// - **Syntax:** `preceded!(BEFORE, THING)`
400 /// - **Output:** `THING`
403 /// extern crate syn;
404 /// #[macro_use] extern crate synom;
407 /// use syn::parse::expr;
409 /// // An expression preceded by ##.
410 /// named!(pound_pound_expr -> Expr,
411 /// preceded!(punct!("##"), expr)
415 /// let input = "## 1 + 1";
417 /// let parsed = pound_pound_expr(input).expect("pound pound expr");
419 /// println!("{:?}", parsed);
423 macro_rules
! preceded
{
424 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $submac2
:ident
!( $
($args2
:tt
)* )) => {
425 match tuple
!($i
, $submac
!($
($args
)*), $submac2
!($
($args2
)*)) {
426 $
crate::IResult
::Done(remaining
, (_
, o
)) => $
crate::IResult
::Done(remaining
, o
),
427 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
431 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $g
:expr
) => {
432 preceded
!($i
, $submac
!($
($args
)*), call
!($g
))
435 ($i
:expr
, $f
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
436 preceded
!($i
, call
!($f
), $submac
!($
($args
)*))
439 ($i
:expr
, $f
:expr
, $g
:expr
) => {
440 preceded
!($i
, call
!($f
), call
!($g
))
444 /// Parse two things, returning the value of the first.
446 /// - **Syntax:** `terminated!(THING, AFTER)`
447 /// - **Output:** `THING`
450 /// extern crate syn;
451 /// #[macro_use] extern crate synom;
454 /// use syn::parse::expr;
456 /// // An expression terminated by ##.
457 /// named!(expr_pound_pound -> Expr,
458 /// terminated!(expr, punct!("##"))
462 /// let input = "1 + 1 ##";
464 /// let parsed = expr_pound_pound(input).expect("expr pound pound");
466 /// println!("{:?}", parsed);
470 macro_rules
! terminated
{
471 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $submac2
:ident
!( $
($args2
:tt
)* )) => {
472 match tuple
!($i
, $submac
!($
($args
)*), $submac2
!($
($args2
)*)) {
473 $
crate::IResult
::Done(remaining
, (o
, _
)) => $
crate::IResult
::Done(remaining
, o
),
474 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
478 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $g
:expr
) => {
479 terminated
!($i
, $submac
!($
($args
)*), call
!($g
))
482 ($i
:expr
, $f
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
483 terminated
!($i
, call
!($f
), $submac
!($
($args
)*))
486 ($i
:expr
, $f
:expr
, $g
:expr
) => {
487 terminated
!($i
, call
!($f
), call
!($g
))
491 /// Parse zero or more values using the given parser.
493 /// - **Syntax:** `many0!(THING)`
494 /// - **Output:** `Vec<THING>`
496 /// You may also be looking for:
498 /// - `separated_list!` - zero or more values with separator
499 /// - `separated_nonempty_list!` - one or more values
500 /// - `terminated_list!` - zero or more, allows trailing separator
503 /// extern crate syn;
504 /// #[macro_use] extern crate synom;
507 /// use syn::parse::item;
509 /// named!(items -> Vec<Item>, many0!(item));
517 /// let parsed = items(input).expect("items");
519 /// assert_eq!(parsed.len(), 2);
520 /// println!("{:?}", parsed);
525 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {{
527 let mut res
= ::std
::vec
::Vec
::new();
531 if input
.is_empty() {
532 ret
= $
crate::IResult
::Done(input
, res
);
536 match $submac
!(input
, $
($args
)*) {
537 $
crate::IResult
::Error
=> {
538 ret
= $
crate::IResult
::Done(input
, res
);
541 $
crate::IResult
::Done(i
, o
) => {
542 // loop trip must always consume (otherwise infinite loops)
543 if i
.len() == input
.len() {
544 ret
= $
crate::IResult
::Error
;
557 ($i
:expr
, $f
:expr
) => {
558 $
crate::many0($i
, $f
)
562 // Improve compile time by compiling this loop only once per type it is used
567 pub fn many0
<'a
, T
>(mut input
: &'a
str,
568 f
: fn(&'a
str) -> IResult
<&'a
str, T
>)
569 -> IResult
<&'a
str, Vec
<T
>> {
570 let mut res
= Vec
::new();
573 if input
.is_empty() {
574 return IResult
::Done(input
, res
);
579 return IResult
::Done(input
, res
);
581 IResult
::Done(i
, o
) => {
582 // loop trip must always consume (otherwise infinite loops)
583 if i
.len() == input
.len() {
584 return IResult
::Error
;
594 /// Parse a value without consuming it from the input data.
596 /// - **Syntax:** `peek!(THING)`
597 /// - **Output:** `THING`
600 /// extern crate syn;
601 /// #[macro_use] extern crate synom;
604 /// use syn::parse::{ident, expr};
605 /// use synom::IResult;
607 /// // Parse an expression that begins with an identifier.
608 /// named!(ident_expr -> Expr,
609 /// preceded!(peek!(ident), expr)
613 /// // begins with an identifier
614 /// let input = "banana + 1";
615 /// let parsed = ident_expr(input).expect("ident");
616 /// println!("{:?}", parsed);
618 /// // does not begin with an identifier
619 /// let input = "1 + banana";
620 /// let err = ident_expr(input);
621 /// assert_eq!(err, IResult::Error);
626 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
627 match $submac
!($i
, $
($args
)*) {
628 $
crate::IResult
::Done(_
, o
) => $
crate::IResult
::Done($i
, o
),
629 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
633 ($i
:expr
, $f
:expr
) => {
638 /// Parse the part of the input up to but not including the given string. Fail
639 /// to parse if the given string is not present in the input.
641 /// - **Syntax:** `take_until!("...")`
642 /// - **Output:** `&str`
645 /// extern crate syn;
646 /// #[macro_use] extern crate synom;
647 /// use synom::IResult;
649 /// // Parse a single line doc comment: /// ...
650 /// named!(single_line_doc -> &str,
651 /// preceded!(punct!("///"), take_until!("\n"))
655 /// let comment = "/// comment\n";
656 /// let parsed = single_line_doc(comment).expect("single line doc comment");
657 /// assert_eq!(parsed, " comment");
661 macro_rules
! take_until
{
662 ($i
:expr
, $substr
:expr
) => {{
663 if $substr
.len() > $i
.len() {
664 $
crate::IResult
::Error
666 let substr_vec
: Vec
<char> = $substr
.chars().collect();
667 let mut window
: Vec
<char> = vec
![];
668 let mut offset
= $i
.len();
669 let mut parsed
= false;
670 for (o
, c
) in $i
.char_indices() {
672 if window
.len() > substr_vec
.len() {
675 if window
== substr_vec
{
678 let window_len
: usize = window
.iter()
679 .map(|x
| x
.len_utf8())
680 .fold(0, |x
, y
| x
+ y
);
681 offset
= o
- window_len
;
686 $
crate::IResult
::Done(&$i
[offset
..], &$i
[..offset
])
688 $
crate::IResult
::Error
694 /// Parse the given string from exactly the current position in the input. You
695 /// almost always want `punct!` or `keyword!` instead of this.
697 /// The `tag!` parser is equivalent to `punct!` but does not ignore leading
698 /// whitespace. Both `punct!` and `keyword!` skip over leading whitespace. See
699 /// an explanation of synom's whitespace handling strategy in the top-level
700 /// crate documentation.
702 /// - **Syntax:** `tag!("...")`
703 /// - **Output:** `"..."`
706 /// extern crate syn;
707 /// #[macro_use] extern crate synom;
710 /// use syn::parse::string;
711 /// use synom::IResult;
713 /// // Parse a proposed syntax for an owned string literal: "abc"s
714 /// named!(owned_string -> String,
716 /// terminated!(string, tag!("s")),
717 /// |lit: StrLit| lit.value
722 /// let input = r#" "abc"s "#;
723 /// let parsed = owned_string(input).expect("owned string literal");
724 /// println!("{:?}", parsed);
726 /// let input = r#" "abc" s "#;
727 /// let err = owned_string(input);
728 /// assert_eq!(err, IResult::Error);
733 ($i
:expr
, $tag
:expr
) => {
734 if $i
.starts_with($tag
) {
735 $
crate::IResult
::Done(&$i
[$tag
.len()..], &$i
[..$tag
.len()])
737 $
crate::IResult
::Error
742 /// Pattern-match the result of a parser to select which other parser to run.
744 /// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
745 /// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
748 /// extern crate syn;
749 /// #[macro_use] extern crate synom;
751 /// use syn::{Ident, Ty};
752 /// use syn::parse::{ident, ty};
765 /// // Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
766 /// named!(unit_type -> UnitType, do_parse!(
767 /// which: alt!(keyword!("struct") | keyword!("enum")) >>
769 /// item: switch!(value!(which),
770 /// "struct" => map!(
772 /// move |_| UnitType::Struct {
778 /// delimited!(punct!("{"), ident, punct!("}")),
779 /// move |variant| UnitType::Enum {
781 /// variant: variant,
789 /// let input = "struct S;";
790 /// let parsed = unit_type(input).expect("unit struct or enum");
791 /// println!("{:?}", parsed);
793 /// let input = "enum E { V }";
794 /// let parsed = unit_type(input).expect("unit struct or enum");
795 /// println!("{:?}", parsed);
799 macro_rules
! switch
{
800 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $
($p
:pat
=> $subrule
:ident
!( $
($args2
:tt
)* ))|* ) => {
801 match $submac
!($i
, $
($args
)*) {
802 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
803 $
crate::IResult
::Done(i
, o
) => match o
{
805 $p
=> $subrule
!(i
, $
($args2
)*),
807 _
=> $
crate::IResult
::Error
,
813 /// Produce the given value without parsing anything. Useful as an argument to
816 /// - **Syntax:** `value!(VALUE)`
817 /// - **Output:** `VALUE`
820 /// extern crate syn;
821 /// #[macro_use] extern crate synom;
823 /// use syn::{Ident, Ty};
824 /// use syn::parse::{ident, ty};
837 /// // Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
838 /// named!(unit_type -> UnitType, do_parse!(
839 /// which: alt!(keyword!("struct") | keyword!("enum")) >>
841 /// item: switch!(value!(which),
842 /// "struct" => map!(
844 /// move |_| UnitType::Struct {
850 /// delimited!(punct!("{"), ident, punct!("}")),
851 /// move |variant| UnitType::Enum {
853 /// variant: variant,
861 /// let input = "struct S;";
862 /// let parsed = unit_type(input).expect("unit struct or enum");
863 /// println!("{:?}", parsed);
865 /// let input = "enum E { V }";
866 /// let parsed = unit_type(input).expect("unit struct or enum");
867 /// println!("{:?}", parsed);
872 ($i
:expr
, $res
:expr
) => {
873 $
crate::IResult
::Done($i
, $res
)
877 /// Value surrounded by a pair of delimiters.
879 /// - **Syntax:** `delimited!(OPEN, THING, CLOSE)`
880 /// - **Output:** `THING`
883 /// extern crate syn;
884 /// #[macro_use] extern crate synom;
887 /// use syn::parse::expr;
889 /// // An expression surrounded by [[ ... ]].
890 /// named!(double_bracket_expr -> Expr,
891 /// delimited!(punct!("[["), expr, punct!("]]"))
895 /// let input = "[[ 1 + 1 ]]";
897 /// let parsed = double_bracket_expr(input).expect("double bracket expr");
899 /// println!("{:?}", parsed);
903 macro_rules
! delimited
{
904 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $
($rest
:tt
)+) => {
905 match tuple_parser
!($i
, (), $submac
!($
($args
)*), $
($rest
)*) {
906 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
907 $
crate::IResult
::Done(i1
, (_
, o
, _
)) => $
crate::IResult
::Done(i1
, o
)
911 ($i
:expr
, $f
:expr
, $
($rest
:tt
)+) => {
912 delimited
!($i
, call
!($f
), $
($rest
)*)
916 /// One or more values separated by some separator. Does not allow a trailing
919 /// - **Syntax:** `separated_nonempty_list!(SEPARATOR, THING)`
920 /// - **Output:** `Vec<THING>`
922 /// You may also be looking for:
924 /// - `separated_list!` - one or more values
925 /// - `terminated_list!` - zero or more, allows trailing separator
926 /// - `many0!` - zero or more, no separator
929 /// extern crate syn;
930 /// #[macro_use] extern crate synom;
933 /// use syn::parse::ty;
935 /// // One or more Rust types separated by commas.
936 /// named!(comma_separated_types -> Vec<Ty>,
937 /// separated_nonempty_list!(punct!(","), ty)
941 /// let input = "&str, Map<K, V>, String";
943 /// let parsed = comma_separated_types(input).expect("comma-separated types");
945 /// assert_eq!(parsed.len(), 3);
946 /// println!("{:?}", parsed);
950 macro_rules
! separated_nonempty_list
{
951 ($i
:expr
, $sep
:ident
!( $
($args
:tt
)* ), $submac
:ident
!( $
($args2
:tt
)* )) => {{
952 let mut res
= ::std
::vec
::Vec
::new();
955 // get the first element
956 match $submac
!(input
, $
($args2
)*) {
957 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
958 $
crate::IResult
::Done(i
, o
) => {
959 if i
.len() == input
.len() {
960 $
crate::IResult
::Error
965 while let $
crate::IResult
::Done(i2
, _
) = $sep
!(input
, $
($args
)*) {
966 if i2
.len() == input
.len() {
970 if let $
crate::IResult
::Done(i3
, o3
) = $submac
!(i2
, $
($args2
)*) {
971 if i3
.len() == i2
.len() {
980 $
crate::IResult
::Done(input
, res
)
986 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ), $g
:expr
) => {
987 separated_nonempty_list
!($i
, $submac
!($
($args
)*), call
!($g
))
990 ($i
:expr
, $f
:expr
, $submac
:ident
!( $
($args
:tt
)* )) => {
991 separated_nonempty_list
!($i
, call
!($f
), $submac
!($
($args
)*))
994 ($i
:expr
, $f
:expr
, $g
:expr
) => {
995 separated_nonempty_list
!($i
, call
!($f
), call
!($g
))
999 /// Run a series of parsers and produce all of the results in a tuple.
1001 /// - **Syntax:** `tuple!(A, B, C, ...)`
1002 /// - **Output:** `(A, B, C, ...)`
1005 /// extern crate syn;
1006 /// #[macro_use] extern crate synom;
1009 /// use syn::parse::ty;
1011 /// named!(two_types -> (Ty, Ty), tuple!(ty, ty));
1014 /// let input = "&str Map<K, V>";
1016 /// let parsed = two_types(input).expect("two types");
1018 /// println!("{:?}", parsed);
1022 macro_rules
! tuple
{
1023 ($i
:expr
, $
($rest
:tt
)*) => {
1024 tuple_parser
!($i
, (), $
($rest
)*)
1028 /// Internal parser, do not use directly.
1031 macro_rules
! tuple_parser
{
1032 ($i
:expr
, ($
($parsed
:tt
),*), $e
:ident
, $
($rest
:tt
)*) => {
1033 tuple_parser
!($i
, ($
($parsed
),*), call
!($e
), $
($rest
)*)
1036 ($i
:expr
, (), $submac
:ident
!( $
($args
:tt
)* ), $
($rest
:tt
)*) => {
1037 match $submac
!($i
, $
($args
)*) {
1038 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1039 $
crate::IResult
::Done(i
, o
) =>
1040 tuple_parser
!(i
, (o
), $
($rest
)*),
1044 ($i
:expr
, ($
($parsed
:tt
)*), $submac
:ident
!( $
($args
:tt
)* ), $
($rest
:tt
)*) => {
1045 match $submac
!($i
, $
($args
)*) {
1046 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1047 $
crate::IResult
::Done(i
, o
) =>
1048 tuple_parser
!(i
, ($
($parsed
)* , o
), $
($rest
)*),
1052 ($i
:expr
, ($
($parsed
:tt
),*), $e
:ident
) => {
1053 tuple_parser
!($i
, ($
($parsed
),*), call
!($e
))
1056 ($i
:expr
, (), $submac
:ident
!( $
($args
:tt
)* )) => {
1057 $submac
!($i
, $
($args
)*)
1060 ($i
:expr
, ($
($parsed
:expr
),*), $submac
:ident
!( $
($args
:tt
)* )) => {
1061 match $submac
!($i
, $
($args
)*) {
1062 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1063 $
crate::IResult
::Done(i
, o
) => $
crate::IResult
::Done(i
, ($
($parsed
),*, o
))
1067 ($i
:expr
, ($
($parsed
:expr
),*)) => {
1068 $
crate::IResult
::Done($i
, ($
($parsed
),*))
1072 /// Run a series of parsers, returning the result of the first one which
1075 /// Optionally allows for the result to be transformed.
1077 /// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
1078 /// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
1081 /// extern crate syn;
1082 /// #[macro_use] extern crate synom;
1085 /// use syn::parse::ident;
1087 /// named!(ident_or_bang -> Ident,
1091 /// punct!("!") => { |_| "BANG".into() }
1096 /// let input = "foo";
1097 /// let parsed = ident_or_bang(input).expect("identifier or `!`");
1098 /// assert_eq!(parsed, "foo");
1100 /// let input = "!";
1101 /// let parsed = ident_or_bang(input).expect("identifier or `!`");
1102 /// assert_eq!(parsed, "BANG");
1107 ($i
:expr
, $e
:ident
| $
($rest
:tt
)*) => {
1108 alt
!($i
, call
!($e
) | $
($rest
)*)
1111 ($i
:expr
, $subrule
:ident
!( $
($args
:tt
)*) | $
($rest
:tt
)*) => {
1112 match $subrule
!($i
, $
($args
)*) {
1113 res @ $
crate::IResult
::Done(_
, _
) => res
,
1114 _
=> alt
!($i
, $
($rest
)*)
1118 ($i
:expr
, $subrule
:ident
!( $
($args
:tt
)* ) => { $gen:expr }
| $
($rest
:tt
)+) => {
1119 match $subrule
!($i
, $
($args
)*) {
1120 $
crate::IResult
::Done(i
, o
) => $
crate::IResult
::Done(i
, $
gen(o
)),
1121 $
crate::IResult
::Error
=> alt
!($i
, $
($rest
)*)
1125 ($i
:expr
, $e
:ident
=> { $gen:expr }
| $
($rest
:tt
)*) => {
1126 alt
!($i
, call
!($e
) => { $gen }
| $
($rest
)*)
1129 ($i
:expr
, $e
:ident
=> { $gen:expr }
) => {
1130 alt
!($i
, call
!($e
) => { $gen }
)
1133 ($i
:expr
, $subrule
:ident
!( $
($args
:tt
)* ) => { $gen:expr }
) => {
1134 match $subrule
!($i
, $
($args
)*) {
1135 $
crate::IResult
::Done(i
, o
) => $
crate::IResult
::Done(i
, $
gen(o
)),
1136 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1140 ($i
:expr
, $e
:ident
) => {
1144 ($i
:expr
, $subrule
:ident
!( $
($args
:tt
)*)) => {
1145 $subrule
!($i
, $
($args
)*)
1149 /// Run a series of parsers, one after another, optionally assigning the results
1150 /// a name. Fail if any of the parsers fails.
1152 /// Produces the result of evaluating the final expression in parentheses with
1153 /// all of the previously named results bound.
1155 /// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
1156 /// - **Output:** `RESULT`
1159 /// extern crate syn;
1160 /// #[macro_use] extern crate synom;
1162 /// use syn::{Ident, TokenTree};
1163 /// use syn::parse::{ident, tt};
1165 /// // Parse a macro invocation like `stringify!($args)`.
1166 /// named!(simple_mac -> (Ident, TokenTree), do_parse!(
1174 /// let input = "stringify!($args)";
1175 /// let (name, body) = simple_mac(input).expect("macro invocation");
1176 /// println!("{:?}", name);
1177 /// println!("{:?}", body);
1181 macro_rules
! do_parse
{
1182 ($i
:expr
, ( $
($rest
:expr
),* )) => {
1183 $
crate::IResult
::Done($i
, ( $
($rest
),* ))
1186 ($i
:expr
, $e
:ident
>> $
($rest
:tt
)*) => {
1187 do_parse
!($i
, call
!($e
) >> $
($rest
)*)
1190 ($i
:expr
, $submac
:ident
!( $
($args
:tt
)* ) >> $
($rest
:tt
)*) => {
1191 match $submac
!($i
, $
($args
)*) {
1192 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1193 $
crate::IResult
::Done(i
, _
) =>
1194 do_parse
!(i
, $
($rest
)*),
1198 ($i
:expr
, $field
:ident
: $e
:ident
>> $
($rest
:tt
)*) => {
1199 do_parse
!($i
, $field
: call
!($e
) >> $
($rest
)*)
1202 ($i
:expr
, $field
:ident
: $submac
:ident
!( $
($args
:tt
)* ) >> $
($rest
:tt
)*) => {
1203 match $submac
!($i
, $
($args
)*) {
1204 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1205 $
crate::IResult
::Done(i
, o
) => {
1207 do_parse
!(i
, $
($rest
)*)
1212 ($i
:expr
, mut $field
:ident
: $e
:ident
>> $
($rest
:tt
)*) => {
1213 do_parse
!($i
, mut $field
: call
!($e
) >> $
($rest
)*)
1216 ($i
:expr
, mut $field
:ident
: $submac
:ident
!( $
($args
:tt
)* ) >> $
($rest
:tt
)*) => {
1217 match $submac
!($i
, $
($args
)*) {
1218 $
crate::IResult
::Error
=> $
crate::IResult
::Error
,
1219 $
crate::IResult
::Done(i
, o
) => {
1221 do_parse
!(i
, $
($rest
)*)