wasm_wrapper_gen_shared/
parsing.rs

1use syn::TokenTree::*;
2use syn::{self, DelimToken};
3use quote::{self, ToTokens};
4
5use MacroError;
6
7pub fn transform_mac_to_items(source: syn::Mac) -> Result<Vec<syn::Item>, MacroError> {
8    if source.tts.len() > 1 {
9        return Err(MacroError::UnexpectedMultiTokenMacro { tokens: source.tts })?;
10    }
11    match source.tts.into_iter().next() {
12        Some(tt) => match tt {
13            Delimited(delimited) => transform_macro_input_to_items(delimited.tts),
14            Token(t) => Err(MacroError::UnexpectedSingleToken { token: t }),
15        },
16        None => Err(MacroError::UnexpectedMultiTokenMacro { tokens: Vec::new() }),
17    }
18}
19
20pub fn transform_macro_input_to_items(
21    tts: Vec<syn::TokenTree>,
22) -> Result<Vec<syn::Item>, MacroError> {
23    let mut found_full = Vec::new();
24
25    let mut so_far = quote::Tokens::new();
26    let mut iter = tts.into_iter();
27    while let Some(token_tree) = iter.next() {
28        match token_tree {
29            // This matches a definition like:
30            // ```
31            // fn a() => modname::funcname;
32            // ```
33            Token(syn::Token::FatArrow) => {
34                // gather all tokens until ';'
35                let mut inner_tokens = Vec::new();
36                while let Some(inner_token) = iter.next() {
37                    match inner_token {
38                        Token(syn::Token::Semi) => break,
39                        _ => inner_tokens.push(inner_token),
40                    }
41                }
42                Delimited(syn::Delimited {
43                    delim: DelimToken::Brace,
44                    tts: inner_tokens,
45                }).to_tokens(&mut so_far);
46                found_full.push(so_far);
47                so_far = quote::Tokens::new();
48            }
49            // This matches a definition like:
50            // ```
51            // fn a() {
52            //     // inline code
53            // }
54            // ```
55            Delimited(syn::Delimited {
56                delim: DelimToken::Brace,
57                ..
58            }) => {
59                token_tree.to_tokens(&mut so_far);
60                found_full.push(so_far);
61                so_far = quote::Tokens::new();
62            }
63            ref other => other.to_tokens(&mut so_far),
64        }
65    }
66
67    if !so_far.as_ref().is_empty() {
68        return Err(MacroError::UnexpectedEndOfMacroInvocation { tokens: so_far });
69    }
70
71    found_full
72        .into_iter()
73        .map(|found| {
74            syn::parse_item(found.as_ref())
75                .map_err(|desc| MacroError::UnexpectedReparseFailure { err_msg: desc })
76        })
77        .collect::<Result<Vec<syn::Item>, MacroError>>()
78}