extendr_macros/
pairs.rs

1//! Internal module for parsing R-like variadic arguments.
2
3use syn::{parse::ParseStream, punctuated::Punctuated, Expr, ExprAssign, ExprPath, Token};
4
5#[derive(Debug)]
6pub(crate) struct Pairs {
7    pub pairs: Punctuated<Expr, Token![,]>,
8}
9
10// Custom parser for a pairlist (a=1, 2, 3) or (1, 2, 3) or (1, b=2, c=3) etc.
11impl syn::parse::Parse for Pairs {
12    fn parse(input: ParseStream) -> syn::Result<Self> {
13        let mut res = Self {
14            pairs: Punctuated::new(),
15        };
16        while !input.is_empty() {
17            res.pairs.push(input.parse::<Expr>()?);
18            if input.is_empty() {
19                break;
20            }
21            input.parse::<Token![,]>()?;
22        }
23        Ok(res)
24    }
25}
26
27impl Pairs {
28    // Having parsed a variadic expression, extract the names and values.
29    pub(crate) fn names_and_values(&self) -> Vec<(String, &Expr)> {
30        self.pairs
31            .iter()
32            .map(|e| -> (String, &Expr) {
33                if let Expr::Assign(ExprAssign { left, right, .. }) = e {
34                    if let Expr::Path(ExprPath { path, .. }) = &**left {
35                        let s = path.get_ident().unwrap().to_string();
36                        return (s, right.as_ref());
37                    }
38                }
39                ("".to_owned(), e)
40            })
41            .collect()
42    }
43}