]> git.proxmox.com Git - rustc.git/blob - vendor/synom/src/lib.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / vendor / synom / src / lib.rs
1 //! Adapted from [`nom`](https://github.com/Geal/nom) by removing the
2 //! `IResult::Incomplete` variant which:
3 //!
4 //! - we don't need,
5 //! - is an unintuitive footgun when working with non-streaming use cases, and
6 //! - more than doubles compilation time.
7 //!
8 //! ## Whitespace handling strategy
9 //!
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!`.
14 //!
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
19 //! free.
20 //!
21 //! For our use case, this strategy is a huge improvement in usability,
22 //! correctness, and compile time over nom's `ws!` strategy.
23
24 extern crate unicode_xid;
25
26 #[doc(hidden)]
27 pub mod space;
28
29 #[doc(hidden)]
30 pub mod helper;
31
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.
37 Done(I, O),
38 /// Parsing failed.
39 Error,
40 }
41
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.
45 ///
46 /// ```rust
47 /// extern crate syn;
48 /// #[macro_use] extern crate synom;
49 ///
50 /// use syn::Ty;
51 /// use syn::parse::ty;
52 ///
53 /// // One or more Rust types separated by commas.
54 /// named!(comma_separated_types -> Vec<Ty>,
55 /// separated_nonempty_list!(punct!(","), ty)
56 /// );
57 ///
58 /// fn main() {
59 /// let input = "&str, Map<K, V>, String";
60 ///
61 /// let parsed = comma_separated_types(input).expect("comma-separated types");
62 ///
63 /// assert_eq!(parsed.len(), 3);
64 /// println!("{:?}", parsed);
65 /// }
66 /// ```
67 pub fn expect(self, name: &str) -> O {
68 match self {
69 IResult::Done(mut rest, o) => {
70 rest = space::skip_whitespace(rest);
71 if rest.is_empty() {
72 o
73 } else {
74 panic!("unparsed tokens after {}: {:?}", name, rest)
75 }
76 }
77 IResult::Error => panic!("failed to parse {}", name),
78 }
79 }
80 }
81
82 /// Define a function from a parser combination.
83 ///
84 /// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
85 ///
86 /// ```rust
87 /// # extern crate syn;
88 /// # #[macro_use] extern crate synom;
89 /// # use syn::Ty;
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)
94 /// );
95 /// # fn main() {}
96 /// ```
97 #[macro_export]
98 macro_rules! named {
99 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
100 fn $name(i: &str) -> $crate::IResult<&str, $o> {
101 $submac!(i, $($args)*)
102 }
103 };
104
105 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
106 pub fn $name(i: &str) -> $crate::IResult<&str, $o> {
107 $submac!(i, $($args)*)
108 }
109 };
110 }
111
112 /// Invoke the given parser function with the passed in arguments.
113 ///
114 /// - **Syntax:** `call!(FUNCTION, ARGS...)`
115 ///
116 /// where the signature of the function is `fn(&str, ARGS...) -> IResult<&str, T>`
117 /// - **Output:** `T`, the result of invoking the function `FUNCTION`
118 ///
119 /// ```rust
120 /// #[macro_use] extern crate synom;
121 ///
122 /// use synom::IResult;
123 ///
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])
130 /// } else {
131 /// IResult::Error
132 /// }
133 /// }
134 ///
135 /// // Parses any string surrounded by tilde characters '~'. Returns the content
136 /// // between the tilde characters.
137 /// named!(surrounded_by_tilde -> &str, delimited!(
138 /// punct!("~"),
139 /// call!(skip_until, '~'),
140 /// punct!("~")
141 /// ));
142 ///
143 /// fn main() {
144 /// let input = "~ abc def ~";
145 ///
146 /// let inner = surrounded_by_tilde(input).expect("surrounded by tilde");
147 ///
148 /// println!("{:?}", inner);
149 /// }
150 /// ```
151 #[macro_export]
152 macro_rules! call {
153 ($i:expr, $fun:expr $(, $args:expr)*) => {
154 $fun($i $(, $args)*)
155 };
156 }
157
158 /// Transform the result of a parser by applying a function or closure.
159 ///
160 /// - **Syntax:** `map!(THING, FN)`
161 /// - **Output:** the return type of function FN applied to THING
162 ///
163 /// ```rust
164 /// extern crate syn;
165 /// #[macro_use] extern crate synom;
166 ///
167 /// use syn::{Item, Ident};
168 /// use syn::parse::item;
169 ///
170 /// fn get_item_ident(item: Item) -> Ident {
171 /// item.ident
172 /// }
173 ///
174 /// // Parses an item and returns the name (identifier) of the item only.
175 /// named!(item_ident -> Ident,
176 /// map!(item, get_item_ident)
177 /// );
178 ///
179 /// // Or equivalently:
180 /// named!(item_ident2 -> Ident,
181 /// map!(item, |i: Item| i.ident)
182 /// );
183 ///
184 /// fn main() {
185 /// let input = "fn foo() {}";
186 ///
187 /// let parsed = item_ident(input).expect("item");
188 ///
189 /// assert_eq!(parsed, "foo");
190 /// }
191 /// ```
192 #[macro_export]
193 macro_rules! map {
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))
199 }
200 }
201 };
202
203 ($i:expr, $f:expr, $g:expr) => {
204 map!($i, call!($f), $g)
205 };
206 }
207
208 /// Parses successfully if the given parser fails to parse. Does not consume any
209 /// of the input.
210 ///
211 /// - **Syntax:** `not!(THING)`
212 /// - **Output:** `()`
213 ///
214 /// ```rust
215 /// extern crate syn;
216 /// #[macro_use] extern crate synom;
217 /// use synom::IResult;
218 ///
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
221 /// // shebang.
222 /// named!(shebang -> &str, preceded!(
223 /// tuple!(tag!("#!"), not!(tag!("["))),
224 /// take_until!("\n")
225 /// ));
226 ///
227 /// fn main() {
228 /// let bin_bash = "#!/bin/bash\n";
229 /// let parsed = shebang(bin_bash).expect("shebang");
230 /// assert_eq!(parsed, "/bin/bash");
231 ///
232 /// let inner_attr = "#![feature(specialization)]\n";
233 /// let err = shebang(inner_attr);
234 /// assert_eq!(err, IResult::Error);
235 /// }
236 /// ```
237 #[macro_export]
238 macro_rules! not {
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, ()),
243 }
244 };
245 }
246
247 /// Conditionally execute the given parser.
248 ///
249 /// If you are familiar with nom, this is nom's `cond_with_error` parser.
250 ///
251 /// - **Syntax:** `cond!(CONDITION, THING)`
252 /// - **Output:** `Some(THING)` if the condition is true, else `None`
253 ///
254 /// ```rust
255 /// extern crate syn;
256 /// #[macro_use] extern crate synom;
257 ///
258 /// use syn::parse::boolean;
259 ///
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!(
265 /// punct!("(") >>
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!(",")) >>
271 /// 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!(","))) >>
276 /// (after)
277 /// )) >>
278 /// // Allow trailing comma if there is no dotdot but there are elements.
279 /// cond!(!before.is_empty() && after.is_none(), option!(punct!(","))) >>
280 /// punct!(")") >>
281 /// (before, after)
282 /// ));
283 ///
284 /// fn main() {
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));
288 ///
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])));
292 ///
293 /// let input = "(.., true)";
294 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
295 /// assert_eq!(parsed, (vec![], Some(vec![true])));
296 ///
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![])));
300 ///
301 /// let input = "(..)";
302 /// let parsed = bools_with_dotdot(input).expect("bools with dotdot");
303 /// assert_eq!(parsed, (vec![], Some(vec![])));
304 /// }
305 /// ```
306 #[macro_export]
307 macro_rules! cond {
308 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
309 if $cond {
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,
313 }
314 } else {
315 $crate::IResult::Done($i, ::std::option::Option::None)
316 }
317 };
318
319 ($i:expr, $cond:expr, $f:expr) => {
320 cond!($i, $cond, call!($f))
321 };
322 }
323
324 /// Fail to parse if condition is false, otherwise parse the given parser.
325 ///
326 /// This is typically used inside of `option!` or `alt!`.
327 ///
328 /// - **Syntax:** `cond_reduce!(CONDITION, THING)`
329 /// - **Output:** `THING`
330 ///
331 /// ```rust
332 /// extern crate syn;
333 /// #[macro_use] extern crate synom;
334 ///
335 /// use syn::parse::boolean;
336 ///
337 /// #[derive(Debug, PartialEq)]
338 /// struct VariadicBools {
339 /// data: Vec<bool>,
340 /// variadic: bool,
341 /// }
342 ///
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:
351 /// //
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!("..."))) >>
360 /// (VariadicBools {
361 /// data: data,
362 /// variadic: variadic.is_some(),
363 /// })
364 /// ));
365 ///
366 /// fn main() {
367 /// let input = "true, true";
368 /// let parsed = variadic_bools(input).expect("variadic bools");
369 /// assert_eq!(parsed, VariadicBools {
370 /// data: vec![true, true],
371 /// variadic: false,
372 /// });
373 ///
374 /// let input = "true, ...";
375 /// let parsed = variadic_bools(input).expect("variadic bools");
376 /// assert_eq!(parsed, VariadicBools {
377 /// data: vec![true],
378 /// variadic: true,
379 /// });
380 /// }
381 /// ```
382 #[macro_export]
383 macro_rules! cond_reduce {
384 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
385 if $cond {
386 $submac!($i, $($args)*)
387 } else {
388 $crate::IResult::Error
389 }
390 };
391
392 ($i:expr, $cond:expr, $f:expr) => {
393 cond_reduce!($i, $cond, call!($f))
394 };
395 }
396
397 /// Parse two things, returning the value of the second.
398 ///
399 /// - **Syntax:** `preceded!(BEFORE, THING)`
400 /// - **Output:** `THING`
401 ///
402 /// ```rust
403 /// extern crate syn;
404 /// #[macro_use] extern crate synom;
405 ///
406 /// use syn::Expr;
407 /// use syn::parse::expr;
408 ///
409 /// // An expression preceded by ##.
410 /// named!(pound_pound_expr -> Expr,
411 /// preceded!(punct!("##"), expr)
412 /// );
413 ///
414 /// fn main() {
415 /// let input = "## 1 + 1";
416 ///
417 /// let parsed = pound_pound_expr(input).expect("pound pound expr");
418 ///
419 /// println!("{:?}", parsed);
420 /// }
421 /// ```
422 #[macro_export]
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,
428 }
429 };
430
431 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
432 preceded!($i, $submac!($($args)*), call!($g))
433 };
434
435 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
436 preceded!($i, call!($f), $submac!($($args)*))
437 };
438
439 ($i:expr, $f:expr, $g:expr) => {
440 preceded!($i, call!($f), call!($g))
441 };
442 }
443
444 /// Parse two things, returning the value of the first.
445 ///
446 /// - **Syntax:** `terminated!(THING, AFTER)`
447 /// - **Output:** `THING`
448 ///
449 /// ```rust
450 /// extern crate syn;
451 /// #[macro_use] extern crate synom;
452 ///
453 /// use syn::Expr;
454 /// use syn::parse::expr;
455 ///
456 /// // An expression terminated by ##.
457 /// named!(expr_pound_pound -> Expr,
458 /// terminated!(expr, punct!("##"))
459 /// );
460 ///
461 /// fn main() {
462 /// let input = "1 + 1 ##";
463 ///
464 /// let parsed = expr_pound_pound(input).expect("expr pound pound");
465 ///
466 /// println!("{:?}", parsed);
467 /// }
468 /// ```
469 #[macro_export]
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,
475 }
476 };
477
478 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
479 terminated!($i, $submac!($($args)*), call!($g))
480 };
481
482 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
483 terminated!($i, call!($f), $submac!($($args)*))
484 };
485
486 ($i:expr, $f:expr, $g:expr) => {
487 terminated!($i, call!($f), call!($g))
488 };
489 }
490
491 /// Parse zero or more values using the given parser.
492 ///
493 /// - **Syntax:** `many0!(THING)`
494 /// - **Output:** `Vec<THING>`
495 ///
496 /// You may also be looking for:
497 ///
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
501 ///
502 /// ```rust
503 /// extern crate syn;
504 /// #[macro_use] extern crate synom;
505 ///
506 /// use syn::Item;
507 /// use syn::parse::item;
508 ///
509 /// named!(items -> Vec<Item>, many0!(item));
510 ///
511 /// fn main() {
512 /// let input = "
513 /// fn a() {}
514 /// fn b() {}
515 /// ";
516 ///
517 /// let parsed = items(input).expect("items");
518 ///
519 /// assert_eq!(parsed.len(), 2);
520 /// println!("{:?}", parsed);
521 /// }
522 /// ```
523 #[macro_export]
524 macro_rules! many0 {
525 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
526 let ret;
527 let mut res = ::std::vec::Vec::new();
528 let mut input = $i;
529
530 loop {
531 if input.is_empty() {
532 ret = $crate::IResult::Done(input, res);
533 break;
534 }
535
536 match $submac!(input, $($args)*) {
537 $crate::IResult::Error => {
538 ret = $crate::IResult::Done(input, res);
539 break;
540 }
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;
545 break;
546 }
547
548 res.push(o);
549 input = i;
550 }
551 }
552 }
553
554 ret
555 }};
556
557 ($i:expr, $f:expr) => {
558 $crate::many0($i, $f)
559 };
560 }
561
562 // Improve compile time by compiling this loop only once per type it is used
563 // with.
564 //
565 // Not public API.
566 #[doc(hidden)]
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();
571
572 loop {
573 if input.is_empty() {
574 return IResult::Done(input, res);
575 }
576
577 match f(input) {
578 IResult::Error => {
579 return IResult::Done(input, res);
580 }
581 IResult::Done(i, o) => {
582 // loop trip must always consume (otherwise infinite loops)
583 if i.len() == input.len() {
584 return IResult::Error;
585 }
586
587 res.push(o);
588 input = i;
589 }
590 }
591 }
592 }
593
594 /// Parse a value without consuming it from the input data.
595 ///
596 /// - **Syntax:** `peek!(THING)`
597 /// - **Output:** `THING`
598 ///
599 /// ```rust
600 /// extern crate syn;
601 /// #[macro_use] extern crate synom;
602 ///
603 /// use syn::Expr;
604 /// use syn::parse::{ident, expr};
605 /// use synom::IResult;
606 ///
607 /// // Parse an expression that begins with an identifier.
608 /// named!(ident_expr -> Expr,
609 /// preceded!(peek!(ident), expr)
610 /// );
611 ///
612 /// fn main() {
613 /// // begins with an identifier
614 /// let input = "banana + 1";
615 /// let parsed = ident_expr(input).expect("ident");
616 /// println!("{:?}", parsed);
617 ///
618 /// // does not begin with an identifier
619 /// let input = "1 + banana";
620 /// let err = ident_expr(input);
621 /// assert_eq!(err, IResult::Error);
622 /// }
623 /// ```
624 #[macro_export]
625 macro_rules! peek {
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,
630 }
631 };
632
633 ($i:expr, $f:expr) => {
634 peek!($i, call!($f))
635 };
636 }
637
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.
640 ///
641 /// - **Syntax:** `take_until!("...")`
642 /// - **Output:** `&str`
643 ///
644 /// ```rust
645 /// extern crate syn;
646 /// #[macro_use] extern crate synom;
647 /// use synom::IResult;
648 ///
649 /// // Parse a single line doc comment: /// ...
650 /// named!(single_line_doc -> &str,
651 /// preceded!(punct!("///"), take_until!("\n"))
652 /// );
653 ///
654 /// fn main() {
655 /// let comment = "/// comment\n";
656 /// let parsed = single_line_doc(comment).expect("single line doc comment");
657 /// assert_eq!(parsed, " comment");
658 /// }
659 /// ```
660 #[macro_export]
661 macro_rules! take_until {
662 ($i:expr, $substr:expr) => {{
663 if $substr.len() > $i.len() {
664 $crate::IResult::Error
665 } else {
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() {
671 window.push(c);
672 if window.len() > substr_vec.len() {
673 window.remove(0);
674 }
675 if window == substr_vec {
676 parsed = true;
677 window.pop();
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;
682 break;
683 }
684 }
685 if parsed {
686 $crate::IResult::Done(&$i[offset..], &$i[..offset])
687 } else {
688 $crate::IResult::Error
689 }
690 }
691 }};
692 }
693
694 /// Parse the given string from exactly the current position in the input. You
695 /// almost always want `punct!` or `keyword!` instead of this.
696 ///
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.
701 ///
702 /// - **Syntax:** `tag!("...")`
703 /// - **Output:** `"..."`
704 ///
705 /// ```rust
706 /// extern crate syn;
707 /// #[macro_use] extern crate synom;
708 ///
709 /// use syn::StrLit;
710 /// use syn::parse::string;
711 /// use synom::IResult;
712 ///
713 /// // Parse a proposed syntax for an owned string literal: "abc"s
714 /// named!(owned_string -> String,
715 /// map!(
716 /// terminated!(string, tag!("s")),
717 /// |lit: StrLit| lit.value
718 /// )
719 /// );
720 ///
721 /// fn main() {
722 /// let input = r#" "abc"s "#;
723 /// let parsed = owned_string(input).expect("owned string literal");
724 /// println!("{:?}", parsed);
725 ///
726 /// let input = r#" "abc" s "#;
727 /// let err = owned_string(input);
728 /// assert_eq!(err, IResult::Error);
729 /// }
730 /// ```
731 #[macro_export]
732 macro_rules! tag {
733 ($i:expr, $tag:expr) => {
734 if $i.starts_with($tag) {
735 $crate::IResult::Done(&$i[$tag.len()..], &$i[..$tag.len()])
736 } else {
737 $crate::IResult::Error
738 }
739 };
740 }
741
742 /// Pattern-match the result of a parser to select which other parser to run.
743 ///
744 /// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
745 /// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
746 ///
747 /// ```rust
748 /// extern crate syn;
749 /// #[macro_use] extern crate synom;
750 ///
751 /// use syn::{Ident, Ty};
752 /// use syn::parse::{ident, ty};
753 ///
754 /// #[derive(Debug)]
755 /// enum UnitType {
756 /// Struct {
757 /// name: Ident,
758 /// },
759 /// Enum {
760 /// name: Ident,
761 /// variant: Ident,
762 /// },
763 /// }
764 ///
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")) >>
768 /// id: ident >>
769 /// item: switch!(value!(which),
770 /// "struct" => map!(
771 /// punct!(";"),
772 /// move |_| UnitType::Struct {
773 /// name: id,
774 /// }
775 /// )
776 /// |
777 /// "enum" => map!(
778 /// delimited!(punct!("{"), ident, punct!("}")),
779 /// move |variant| UnitType::Enum {
780 /// name: id,
781 /// variant: variant,
782 /// }
783 /// )
784 /// ) >>
785 /// (item)
786 /// ));
787 ///
788 /// fn main() {
789 /// let input = "struct S;";
790 /// let parsed = unit_type(input).expect("unit struct or enum");
791 /// println!("{:?}", parsed);
792 ///
793 /// let input = "enum E { V }";
794 /// let parsed = unit_type(input).expect("unit struct or enum");
795 /// println!("{:?}", parsed);
796 /// }
797 /// ```
798 #[macro_export]
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 {
804 $(
805 $p => $subrule!(i, $($args2)*),
806 )*
807 _ => $crate::IResult::Error,
808 }
809 }
810 };
811 }
812
813 /// Produce the given value without parsing anything. Useful as an argument to
814 /// `switch!`.
815 ///
816 /// - **Syntax:** `value!(VALUE)`
817 /// - **Output:** `VALUE`
818 ///
819 /// ```rust
820 /// extern crate syn;
821 /// #[macro_use] extern crate synom;
822 ///
823 /// use syn::{Ident, Ty};
824 /// use syn::parse::{ident, ty};
825 ///
826 /// #[derive(Debug)]
827 /// enum UnitType {
828 /// Struct {
829 /// name: Ident,
830 /// },
831 /// Enum {
832 /// name: Ident,
833 /// variant: Ident,
834 /// },
835 /// }
836 ///
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")) >>
840 /// id: ident >>
841 /// item: switch!(value!(which),
842 /// "struct" => map!(
843 /// punct!(";"),
844 /// move |_| UnitType::Struct {
845 /// name: id,
846 /// }
847 /// )
848 /// |
849 /// "enum" => map!(
850 /// delimited!(punct!("{"), ident, punct!("}")),
851 /// move |variant| UnitType::Enum {
852 /// name: id,
853 /// variant: variant,
854 /// }
855 /// )
856 /// ) >>
857 /// (item)
858 /// ));
859 ///
860 /// fn main() {
861 /// let input = "struct S;";
862 /// let parsed = unit_type(input).expect("unit struct or enum");
863 /// println!("{:?}", parsed);
864 ///
865 /// let input = "enum E { V }";
866 /// let parsed = unit_type(input).expect("unit struct or enum");
867 /// println!("{:?}", parsed);
868 /// }
869 /// ```
870 #[macro_export]
871 macro_rules! value {
872 ($i:expr, $res:expr) => {
873 $crate::IResult::Done($i, $res)
874 };
875 }
876
877 /// Value surrounded by a pair of delimiters.
878 ///
879 /// - **Syntax:** `delimited!(OPEN, THING, CLOSE)`
880 /// - **Output:** `THING`
881 ///
882 /// ```rust
883 /// extern crate syn;
884 /// #[macro_use] extern crate synom;
885 ///
886 /// use syn::Expr;
887 /// use syn::parse::expr;
888 ///
889 /// // An expression surrounded by [[ ... ]].
890 /// named!(double_bracket_expr -> Expr,
891 /// delimited!(punct!("[["), expr, punct!("]]"))
892 /// );
893 ///
894 /// fn main() {
895 /// let input = "[[ 1 + 1 ]]";
896 ///
897 /// let parsed = double_bracket_expr(input).expect("double bracket expr");
898 ///
899 /// println!("{:?}", parsed);
900 /// }
901 /// ```
902 #[macro_export]
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)
908 }
909 };
910
911 ($i:expr, $f:expr, $($rest:tt)+) => {
912 delimited!($i, call!($f), $($rest)*)
913 };
914 }
915
916 /// One or more values separated by some separator. Does not allow a trailing
917 /// separator.
918 ///
919 /// - **Syntax:** `separated_nonempty_list!(SEPARATOR, THING)`
920 /// - **Output:** `Vec<THING>`
921 ///
922 /// You may also be looking for:
923 ///
924 /// - `separated_list!` - one or more values
925 /// - `terminated_list!` - zero or more, allows trailing separator
926 /// - `many0!` - zero or more, no separator
927 ///
928 /// ```rust
929 /// extern crate syn;
930 /// #[macro_use] extern crate synom;
931 ///
932 /// use syn::Ty;
933 /// use syn::parse::ty;
934 ///
935 /// // One or more Rust types separated by commas.
936 /// named!(comma_separated_types -> Vec<Ty>,
937 /// separated_nonempty_list!(punct!(","), ty)
938 /// );
939 ///
940 /// fn main() {
941 /// let input = "&str, Map<K, V>, String";
942 ///
943 /// let parsed = comma_separated_types(input).expect("comma-separated types");
944 ///
945 /// assert_eq!(parsed.len(), 3);
946 /// println!("{:?}", parsed);
947 /// }
948 /// ```
949 #[macro_export]
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();
953 let mut input = $i;
954
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
961 } else {
962 res.push(o);
963 input = i;
964
965 while let $crate::IResult::Done(i2, _) = $sep!(input, $($args)*) {
966 if i2.len() == input.len() {
967 break;
968 }
969
970 if let $crate::IResult::Done(i3, o3) = $submac!(i2, $($args2)*) {
971 if i3.len() == i2.len() {
972 break;
973 }
974 res.push(o3);
975 input = i3;
976 } else {
977 break;
978 }
979 }
980 $crate::IResult::Done(input, res)
981 }
982 }
983 }
984 }};
985
986 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
987 separated_nonempty_list!($i, $submac!($($args)*), call!($g))
988 };
989
990 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
991 separated_nonempty_list!($i, call!($f), $submac!($($args)*))
992 };
993
994 ($i:expr, $f:expr, $g:expr) => {
995 separated_nonempty_list!($i, call!($f), call!($g))
996 };
997 }
998
999 /// Run a series of parsers and produce all of the results in a tuple.
1000 ///
1001 /// - **Syntax:** `tuple!(A, B, C, ...)`
1002 /// - **Output:** `(A, B, C, ...)`
1003 ///
1004 /// ```rust
1005 /// extern crate syn;
1006 /// #[macro_use] extern crate synom;
1007 ///
1008 /// use syn::Ty;
1009 /// use syn::parse::ty;
1010 ///
1011 /// named!(two_types -> (Ty, Ty), tuple!(ty, ty));
1012 ///
1013 /// fn main() {
1014 /// let input = "&str Map<K, V>";
1015 ///
1016 /// let parsed = two_types(input).expect("two types");
1017 ///
1018 /// println!("{:?}", parsed);
1019 /// }
1020 /// ```
1021 #[macro_export]
1022 macro_rules! tuple {
1023 ($i:expr, $($rest:tt)*) => {
1024 tuple_parser!($i, (), $($rest)*)
1025 };
1026 }
1027
1028 /// Internal parser, do not use directly.
1029 #[doc(hidden)]
1030 #[macro_export]
1031 macro_rules! tuple_parser {
1032 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
1033 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
1034 };
1035
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)*),
1041 }
1042 };
1043
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)*),
1049 }
1050 };
1051
1052 ($i:expr, ($($parsed:tt),*), $e:ident) => {
1053 tuple_parser!($i, ($($parsed),*), call!($e))
1054 };
1055
1056 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
1057 $submac!($i, $($args)*)
1058 };
1059
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))
1064 }
1065 };
1066
1067 ($i:expr, ($($parsed:expr),*)) => {
1068 $crate::IResult::Done($i, ($($parsed),*))
1069 };
1070 }
1071
1072 /// Run a series of parsers, returning the result of the first one which
1073 /// succeeds.
1074 ///
1075 /// Optionally allows for the result to be transformed.
1076 ///
1077 /// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
1078 /// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
1079 ///
1080 /// ```rust
1081 /// extern crate syn;
1082 /// #[macro_use] extern crate synom;
1083 ///
1084 /// use syn::Ident;
1085 /// use syn::parse::ident;
1086 ///
1087 /// named!(ident_or_bang -> Ident,
1088 /// alt!(
1089 /// ident
1090 /// |
1091 /// punct!("!") => { |_| "BANG".into() }
1092 /// )
1093 /// );
1094 ///
1095 /// fn main() {
1096 /// let input = "foo";
1097 /// let parsed = ident_or_bang(input).expect("identifier or `!`");
1098 /// assert_eq!(parsed, "foo");
1099 ///
1100 /// let input = "!";
1101 /// let parsed = ident_or_bang(input).expect("identifier or `!`");
1102 /// assert_eq!(parsed, "BANG");
1103 /// }
1104 /// ```
1105 #[macro_export]
1106 macro_rules! alt {
1107 ($i:expr, $e:ident | $($rest:tt)*) => {
1108 alt!($i, call!($e) | $($rest)*)
1109 };
1110
1111 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
1112 match $subrule!($i, $($args)*) {
1113 res @ $crate::IResult::Done(_, _) => res,
1114 _ => alt!($i, $($rest)*)
1115 }
1116 };
1117
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)*)
1122 }
1123 };
1124
1125 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
1126 alt!($i, call!($e) => { $gen } | $($rest)*)
1127 };
1128
1129 ($i:expr, $e:ident => { $gen:expr }) => {
1130 alt!($i, call!($e) => { $gen })
1131 };
1132
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,
1137 }
1138 };
1139
1140 ($i:expr, $e:ident) => {
1141 alt!($i, call!($e))
1142 };
1143
1144 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
1145 $subrule!($i, $($args)*)
1146 };
1147 }
1148
1149 /// Run a series of parsers, one after another, optionally assigning the results
1150 /// a name. Fail if any of the parsers fails.
1151 ///
1152 /// Produces the result of evaluating the final expression in parentheses with
1153 /// all of the previously named results bound.
1154 ///
1155 /// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
1156 /// - **Output:** `RESULT`
1157 ///
1158 /// ```rust
1159 /// extern crate syn;
1160 /// #[macro_use] extern crate synom;
1161 ///
1162 /// use syn::{Ident, TokenTree};
1163 /// use syn::parse::{ident, tt};
1164 ///
1165 /// // Parse a macro invocation like `stringify!($args)`.
1166 /// named!(simple_mac -> (Ident, TokenTree), do_parse!(
1167 /// name: ident >>
1168 /// punct!("!") >>
1169 /// body: tt >>
1170 /// (name, body)
1171 /// ));
1172 ///
1173 /// fn main() {
1174 /// let input = "stringify!($args)";
1175 /// let (name, body) = simple_mac(input).expect("macro invocation");
1176 /// println!("{:?}", name);
1177 /// println!("{:?}", body);
1178 /// }
1179 /// ```
1180 #[macro_export]
1181 macro_rules! do_parse {
1182 ($i:expr, ( $($rest:expr),* )) => {
1183 $crate::IResult::Done($i, ( $($rest),* ))
1184 };
1185
1186 ($i:expr, $e:ident >> $($rest:tt)*) => {
1187 do_parse!($i, call!($e) >> $($rest)*)
1188 };
1189
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)*),
1195 }
1196 };
1197
1198 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
1199 do_parse!($i, $field: call!($e) >> $($rest)*)
1200 };
1201
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) => {
1206 let $field = o;
1207 do_parse!(i, $($rest)*)
1208 },
1209 }
1210 };
1211
1212 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
1213 do_parse!($i, mut $field: call!($e) >> $($rest)*)
1214 };
1215
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) => {
1220 let mut $field = o;
1221 do_parse!(i, $($rest)*)
1222 },
1223 }
1224 };
1225 }