]> git.proxmox.com Git - rustc.git/blob - src/vendor/synom/src/helper.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / synom / src / helper.rs
1 use IResult;
2 use space::{skip_whitespace, word_break};
3
4 /// Parse a piece of punctuation like "+" or "+=".
5 ///
6 /// See also `keyword!` for parsing keywords, which are subtly different from
7 /// punctuation.
8 ///
9 /// - **Syntax:** `punct!("...")`
10 /// - **Output:** `&str`
11 ///
12 /// ```rust
13 /// extern crate syn;
14 /// #[macro_use] extern crate synom;
15 ///
16 /// // Parse zero or more bangs.
17 /// named!(many_bangs -> Vec<&str>,
18 /// many0!(punct!("!"))
19 /// );
20 ///
21 /// fn main() {
22 /// let input = "!! !";
23 /// let parsed = many_bangs(input).expect("bangs");
24 /// assert_eq!(parsed, ["!", "!", "!"]);
25 /// }
26 /// ```
27 #[macro_export]
28 macro_rules! punct {
29 ($i:expr, $punct:expr) => {
30 $crate::helper::punct($i, $punct)
31 };
32 }
33
34 // Not public API.
35 #[doc(hidden)]
36 pub fn punct<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, &'a str> {
37 let input = skip_whitespace(input);
38 if input.starts_with(token) {
39 IResult::Done(&input[token.len()..], token)
40 } else {
41 IResult::Error
42 }
43 }
44
45 /// Parse a keyword like "fn" or "struct".
46 ///
47 /// See also `punct!` for parsing punctuation, which are subtly different from
48 /// keywords.
49 ///
50 /// - **Syntax:** `keyword!("...")`
51 /// - **Output:** `&str`
52 ///
53 /// ```rust
54 /// extern crate syn;
55 /// #[macro_use] extern crate synom;
56 ///
57 /// use synom::IResult;
58 ///
59 /// // Parse zero or more "bang" keywords.
60 /// named!(many_bangs -> Vec<&str>,
61 /// terminated!(
62 /// many0!(keyword!("bang")),
63 /// punct!(";")
64 /// )
65 /// );
66 ///
67 /// fn main() {
68 /// let input = "bang bang bang;";
69 /// let parsed = many_bangs(input).expect("bangs");
70 /// assert_eq!(parsed, ["bang", "bang", "bang"]);
71 ///
72 /// let input = "bangbang;";
73 /// let err = many_bangs(input);
74 /// assert_eq!(err, IResult::Error);
75 /// }
76 /// ```
77 #[macro_export]
78 macro_rules! keyword {
79 ($i:expr, $keyword:expr) => {
80 $crate::helper::keyword($i, $keyword)
81 };
82 }
83
84 // Not public API.
85 #[doc(hidden)]
86 pub fn keyword<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, &'a str> {
87 match punct(input, token) {
88 IResult::Done(rest, _) => {
89 match word_break(rest) {
90 IResult::Done(_, _) => IResult::Done(rest, token),
91 IResult::Error => IResult::Error,
92 }
93 }
94 IResult::Error => IResult::Error,
95 }
96 }
97
98 /// Turn a failed parse into `None` and a successful parse into `Some`.
99 ///
100 /// - **Syntax:** `option!(THING)`
101 /// - **Output:** `Option<THING>`
102 ///
103 /// ```rust
104 /// extern crate syn;
105 /// #[macro_use] extern crate synom;
106 ///
107 /// named!(maybe_bang -> Option<&str>, option!(punct!("!")));
108 ///
109 /// fn main() {
110 /// let input = "!";
111 /// let parsed = maybe_bang(input).expect("maybe bang");
112 /// assert_eq!(parsed, Some("!"));
113 ///
114 /// let input = "";
115 /// let parsed = maybe_bang(input).expect("maybe bang");
116 /// assert_eq!(parsed, None);
117 /// }
118 /// ```
119 #[macro_export]
120 macro_rules! option {
121 ($i:expr, $submac:ident!( $($args:tt)* )) => {
122 match $submac!($i, $($args)*) {
123 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, Some(o)),
124 $crate::IResult::Error => $crate::IResult::Done($i, None),
125 }
126 };
127
128 ($i:expr, $f:expr) => {
129 option!($i, call!($f));
130 };
131 }
132
133 /// Turn a failed parse into an empty vector. The argument parser must itself
134 /// return a vector.
135 ///
136 /// This is often more convenient than `option!(...)` when the argument produces
137 /// a vector.
138 ///
139 /// - **Syntax:** `opt_vec!(THING)`
140 /// - **Output:** `THING`, which must be `Vec<T>`
141 ///
142 /// ```rust
143 /// extern crate syn;
144 /// #[macro_use] extern crate synom;
145 ///
146 /// use syn::{Lifetime, Ty};
147 /// use syn::parse::{lifetime, ty};
148 ///
149 /// named!(bound_lifetimes -> (Vec<Lifetime>, Ty), tuple!(
150 /// opt_vec!(do_parse!(
151 /// keyword!("for") >>
152 /// punct!("<") >>
153 /// lifetimes: terminated_list!(punct!(","), lifetime) >>
154 /// punct!(">") >>
155 /// (lifetimes)
156 /// )),
157 /// ty
158 /// ));
159 ///
160 /// fn main() {
161 /// let input = "for<'a, 'b> fn(&'a A) -> &'b B";
162 /// let parsed = bound_lifetimes(input).expect("bound lifetimes");
163 /// assert_eq!(parsed.0, [Lifetime::new("'a"), Lifetime::new("'b")]);
164 /// println!("{:?}", parsed);
165 ///
166 /// let input = "From<String>";
167 /// let parsed = bound_lifetimes(input).expect("bound lifetimes");
168 /// assert!(parsed.0.is_empty());
169 /// println!("{:?}", parsed);
170 /// }
171 /// ```
172 #[macro_export]
173 macro_rules! opt_vec {
174 ($i:expr, $submac:ident!( $($args:tt)* )) => {
175 match $submac!($i, $($args)*) {
176 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, o),
177 $crate::IResult::Error => $crate::IResult::Done($i, Vec::new()),
178 }
179 };
180 }
181
182 /// Parses nothing and always succeeds.
183 ///
184 /// This can be useful as a fallthrough case in `alt!`.
185 ///
186 /// - **Syntax:** `epsilon!()`
187 /// - **Output:** `()`
188 ///
189 /// ```rust
190 /// extern crate syn;
191 /// #[macro_use] extern crate synom;
192 ///
193 /// use syn::Mutability;
194 ///
195 /// named!(mutability -> Mutability, alt!(
196 /// keyword!("mut") => { |_| Mutability::Mutable }
197 /// |
198 /// epsilon!() => { |_| Mutability::Immutable }
199 /// ));
200 ///
201 /// fn main() {
202 /// let input = "mut";
203 /// let parsed = mutability(input).expect("mutability");
204 /// assert_eq!(parsed, Mutability::Mutable);
205 ///
206 /// let input = "";
207 /// let parsed = mutability(input).expect("mutability");
208 /// assert_eq!(parsed, Mutability::Immutable);
209 /// }
210 /// ```
211 #[macro_export]
212 macro_rules! epsilon {
213 ($i:expr,) => {
214 $crate::IResult::Done($i, ())
215 };
216 }
217
218 /// Run a parser, binding the result to a name, and then evaluating an
219 /// expression.
220 ///
221 /// Discards the result of the expression and parser.
222 ///
223 /// - **Syntax:** `tap!(NAME : THING => EXPR)`
224 /// - **Output:** `()`
225 ///
226 /// ```rust
227 /// extern crate syn;
228 /// #[macro_use] extern crate synom;
229 ///
230 /// use syn::{Expr, ExprKind};
231 /// use syn::parse::expr;
232 ///
233 /// named!(expr_with_arrow_call -> Expr, do_parse!(
234 /// mut e: expr >>
235 /// many0!(tap!(arg: tuple!(punct!("=>"), expr) => {
236 /// e = Expr {
237 /// node: ExprKind::Call(Box::new(e), vec![arg.1]),
238 /// attrs: Vec::new(),
239 /// };
240 /// })) >>
241 /// (e)
242 /// ));
243 ///
244 /// fn main() {
245 /// let input = "something => argument1 => argument2";
246 ///
247 /// let parsed = expr_with_arrow_call(input).expect("expr with arrow call");
248 ///
249 /// println!("{:?}", parsed);
250 /// }
251 /// ```
252 #[doc(hidden)]
253 #[macro_export]
254 macro_rules! tap {
255 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
256 match $submac!($i, $($args)*) {
257 $crate::IResult::Done(i, o) => {
258 let $name = o;
259 $e;
260 $crate::IResult::Done(i, ())
261 }
262 $crate::IResult::Error => $crate::IResult::Error,
263 }
264 };
265
266 ($i:expr, $name:ident : $f:expr => $e:expr) => {
267 tap!($i, $name: call!($f) => $e);
268 };
269 }
270
271 /// Zero or more values separated by some separator. Does not allow a trailing
272 /// seperator.
273 ///
274 /// - **Syntax:** `separated_list!(punct!("..."), THING)`
275 /// - **Output:** `Vec<THING>`
276 ///
277 /// You may also be looking for:
278 ///
279 /// - `separated_nonempty_list!` - one or more values
280 /// - `terminated_list!` - zero or more, allows trailing separator
281 /// - `many0!` - zero or more, no separator
282 ///
283 /// ```rust
284 /// extern crate syn;
285 /// #[macro_use] extern crate synom;
286 ///
287 /// use syn::Expr;
288 /// use syn::parse::expr;
289 ///
290 /// named!(expr_list -> Vec<Expr>,
291 /// separated_list!(punct!(","), expr)
292 /// );
293 ///
294 /// fn main() {
295 /// let input = "1 + 1, things, Construct { this: thing }";
296 ///
297 /// let parsed = expr_list(input).expect("expr list");
298 /// assert_eq!(parsed.len(), 3);
299 /// }
300 /// ```
301 ///
302 /// ```rust
303 /// extern crate syn;
304 /// #[macro_use] extern crate synom;
305 ///
306 /// use syn::Ident;
307 /// use syn::parse::ident;
308 ///
309 /// named!(run_on -> Vec<Ident>,
310 /// terminated!(
311 /// separated_list!(keyword!("and"), preceded!(punct!("$"), ident)),
312 /// punct!("...")
313 /// )
314 /// );
315 ///
316 /// fn main() {
317 /// let input = "$expr and $ident and $pat ...";
318 ///
319 /// let parsed = run_on(input).expect("run-on sentence");
320 /// assert_eq!(parsed.len(), 3);
321 /// assert_eq!(parsed[0], "expr");
322 /// assert_eq!(parsed[1], "ident");
323 /// assert_eq!(parsed[2], "pat");
324 /// }
325 /// ```
326 #[macro_export]
327 macro_rules! separated_list {
328 // Try to use this branch if possible - makes a difference in compile time.
329 ($i:expr, punct!($sep:expr), $f:ident) => {
330 $crate::helper::separated_list($i, $sep, $f, false)
331 };
332
333 ($i:expr, $sepmac:ident!( $($separgs:tt)* ), $fmac:ident!( $($fargs:tt)* )) => {{
334 let mut res = ::std::vec::Vec::new();
335 let mut input = $i;
336
337 // get the first element
338 match $fmac!(input, $($fargs)*) {
339 $crate::IResult::Error => $crate::IResult::Done(input, res),
340 $crate::IResult::Done(i, o) => {
341 if i.len() == input.len() {
342 $crate::IResult::Error
343 } else {
344 res.push(o);
345 input = i;
346
347 // get the separator first
348 while let $crate::IResult::Done(i2, _) = $sepmac!(input, $($separgs)*) {
349 if i2.len() == input.len() {
350 break;
351 }
352
353 // get the element next
354 if let $crate::IResult::Done(i3, o3) = $fmac!(i2, $($fargs)*) {
355 if i3.len() == i2.len() {
356 break;
357 }
358 res.push(o3);
359 input = i3;
360 } else {
361 break;
362 }
363 }
364 $crate::IResult::Done(input, res)
365 }
366 }
367 }
368 }};
369
370 ($i:expr, $sepmac:ident!( $($separgs:tt)* ), $f:expr) => {
371 separated_list!($i, $sepmac!($($separgs)*), call!($f))
372 };
373
374 ($i:expr, $sep:expr, $fmac:ident!( $($fargs:tt)* )) => {
375 separated_list!($i, call!($sep), $fmac!($($fargs)*))
376 };
377
378 ($i:expr, $sep:expr, $f:expr) => {
379 separated_list!($i, call!($sep), call!($f))
380 };
381 }
382
383 /// Zero or more values separated by some separator. A trailing separator is
384 /// allowed.
385 ///
386 /// - **Syntax:** `terminated_list!(punct!("..."), THING)`
387 /// - **Output:** `Vec<THING>`
388 ///
389 /// You may also be looking for:
390 ///
391 /// - `separated_list!` - zero or more, allows trailing separator
392 /// - `separated_nonempty_list!` - one or more values
393 /// - `many0!` - zero or more, no separator
394 ///
395 /// ```rust
396 /// extern crate syn;
397 /// #[macro_use] extern crate synom;
398 ///
399 /// use syn::Expr;
400 /// use syn::parse::expr;
401 ///
402 /// named!(expr_list -> Vec<Expr>,
403 /// terminated_list!(punct!(","), expr)
404 /// );
405 ///
406 /// fn main() {
407 /// let input = "1 + 1, things, Construct { this: thing },";
408 ///
409 /// let parsed = expr_list(input).expect("expr list");
410 /// assert_eq!(parsed.len(), 3);
411 /// }
412 /// ```
413 ///
414 /// ```rust
415 /// extern crate syn;
416 /// #[macro_use] extern crate synom;
417 ///
418 /// use syn::Ident;
419 /// use syn::parse::ident;
420 ///
421 /// named!(run_on -> Vec<Ident>,
422 /// terminated!(
423 /// terminated_list!(keyword!("and"), preceded!(punct!("$"), ident)),
424 /// punct!("...")
425 /// )
426 /// );
427 ///
428 /// fn main() {
429 /// let input = "$expr and $ident and $pat and ...";
430 ///
431 /// let parsed = run_on(input).expect("run-on sentence");
432 /// assert_eq!(parsed.len(), 3);
433 /// assert_eq!(parsed[0], "expr");
434 /// assert_eq!(parsed[1], "ident");
435 /// assert_eq!(parsed[2], "pat");
436 /// }
437 /// ```
438 #[macro_export]
439 macro_rules! terminated_list {
440 // Try to use this branch if possible - makes a difference in compile time.
441 ($i:expr, punct!($sep:expr), $f:ident) => {
442 $crate::helper::separated_list($i, $sep, $f, true)
443 };
444
445 ($i:expr, $sepmac:ident!( $($separgs:tt)* ), $fmac:ident!( $($fargs:tt)* )) => {{
446 let mut res = ::std::vec::Vec::new();
447 let mut input = $i;
448
449 // get the first element
450 match $fmac!(input, $($fargs)*) {
451 $crate::IResult::Error => $crate::IResult::Done(input, res),
452 $crate::IResult::Done(i, o) => {
453 if i.len() == input.len() {
454 $crate::IResult::Error
455 } else {
456 res.push(o);
457 input = i;
458
459 // get the separator first
460 while let $crate::IResult::Done(i2, _) = $sepmac!(input, $($separgs)*) {
461 if i2.len() == input.len() {
462 break;
463 }
464
465 // get the element next
466 if let $crate::IResult::Done(i3, o3) = $fmac!(i2, $($fargs)*) {
467 if i3.len() == i2.len() {
468 break;
469 }
470 res.push(o3);
471 input = i3;
472 } else {
473 break;
474 }
475 }
476 if let $crate::IResult::Done(after, _) = $sepmac!(input, $($separgs)*) {
477 input = after;
478 }
479 $crate::IResult::Done(input, res)
480 }
481 }
482 }
483 }};
484
485 ($i:expr, $sepmac:ident!( $($separgs:tt)* ), $f:expr) => {
486 terminated_list!($i, $sepmac!($($separgs)*), call!($f))
487 };
488
489 ($i:expr, $sep:expr, $fmac:ident!( $($fargs:tt)* )) => {
490 terminated_list!($i, call!($sep), $fmac!($($fargs)*))
491 };
492
493 ($i:expr, $sep:expr, $f:expr) => {
494 terminated_list!($i, call!($sep), call!($f))
495 };
496 }
497
498 // Not public API.
499 #[doc(hidden)]
500 pub fn separated_list<'a, T>(mut input: &'a str,
501 sep: &'static str,
502 f: fn(&'a str) -> IResult<&'a str, T>,
503 terminated: bool)
504 -> IResult<&'a str, Vec<T>> {
505 let mut res = Vec::new();
506
507 // get the first element
508 match f(input) {
509 IResult::Error => IResult::Done(input, res),
510 IResult::Done(i, o) => {
511 if i.len() == input.len() {
512 IResult::Error
513 } else {
514 res.push(o);
515 input = i;
516
517 // get the separator first
518 while let IResult::Done(i2, _) = punct(input, sep) {
519 if i2.len() == input.len() {
520 break;
521 }
522
523 // get the element next
524 if let IResult::Done(i3, o3) = f(i2) {
525 if i3.len() == i2.len() {
526 break;
527 }
528 res.push(o3);
529 input = i3;
530 } else {
531 break;
532 }
533 }
534 if terminated {
535 if let IResult::Done(after, _) = punct(input, sep) {
536 input = after;
537 }
538 }
539 IResult::Done(input, res)
540 }
541 }
542 }
543 }