union_impl/expr_chain/
utils.rs

1//!
2//! Utils for `union!` macro parsing and code generation.
3//!
4
5use proc_macro2::{TokenStream, TokenTree};
6use quote::ToTokens;
7use syn::parse::ParseStream;
8use syn::{parse2, Expr};
9
10use super::chain::{Unit, UnitResult};
11use super::GroupDeterminer;
12
13///
14/// Returns true if given stream can be parsed as `Expr`.
15///
16pub fn is_valid_expr(input: TokenStream) -> bool {
17    syn::parse2::<Expr>(input).is_ok()
18}
19
20///
21/// Returns true if expr is {...}.
22///
23pub fn is_block_expr(expr: &Expr) -> bool {
24    match *expr {
25        Expr::Block(_) => true,
26        _ => false,
27    }
28}
29
30///
31/// Parses input `ParseStream` until one of provided `GroupDeterminer`'s check will be valid or it reaches end.
32///
33pub fn parse_until(input: ParseStream, group_determiners: &[GroupDeterminer]) -> UnitResult {
34    let mut tokens = TokenStream::new();
35    let mut next_group = None;
36
37    while !input.is_empty() && {
38        let possible_group = group_determiners
39            .iter()
40            .find(|group| group.check_input(&input));
41        possible_group.is_none()
42            || possible_group
43                .map(|group| !group.check_parsed(tokens.clone()))
44                .unwrap_or(false)
45            || {
46                next_group = possible_group;
47                false
48            }
49    } {
50        let next: TokenTree = input.parse()?;
51        next.to_tokens(&mut tokens);
52    }
53
54    //
55    // Parses group determiner's tokens. (for ex. => -> |> etc.)
56    //
57    let _ = next_group
58        .as_ref()
59        .and_then(|group| group.erase_input(input).ok());
60
61    Ok(Unit {
62        expr: parse2(tokens)?,
63        next_group_type: next_group.and_then(GroupDeterminer::get_group_type),
64    })
65}