• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::syntax::file::Module;
2 use crate::syntax::namespace::Namespace;
3 use syn::parse::discouraged::Speculative;
4 use syn::parse::{Error, Parse, ParseStream, Result};
5 use syn::{braced, Attribute, Ident, Item, Token, Visibility};
6 
7 pub struct File {
8     pub modules: Vec<Module>,
9 }
10 
11 impl Parse for File {
parse(input: ParseStream) -> Result<Self>12     fn parse(input: ParseStream) -> Result<Self> {
13         let mut modules = Vec::new();
14         input.call(Attribute::parse_inner)?;
15         parse(input, &mut modules)?;
16         Ok(File { modules })
17     }
18 }
19 
parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()>20 fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
21     while !input.is_empty() {
22         let mut cxx_bridge = false;
23         let mut namespace = Namespace::ROOT;
24         let mut attrs = input.call(Attribute::parse_outer)?;
25         for attr in &attrs {
26             let path = &attr.path.segments;
27             if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
28                 cxx_bridge = true;
29                 namespace = parse_args(attr)?;
30                 break;
31             }
32         }
33 
34         let ahead = input.fork();
35         ahead.parse::<Visibility>()?;
36         ahead.parse::<Option<Token![unsafe]>>()?;
37         if !ahead.peek(Token![mod]) {
38             let item: Item = input.parse()?;
39             if cxx_bridge {
40                 return Err(Error::new_spanned(item, "expected a module"));
41             }
42             continue;
43         }
44 
45         if cxx_bridge {
46             let mut module: Module = input.parse()?;
47             module.namespace = namespace;
48             attrs.extend(module.attrs);
49             module.attrs = attrs;
50             modules.push(module);
51         } else {
52             input.advance_to(&ahead);
53             input.parse::<Token![mod]>()?;
54             input.parse::<Ident>()?;
55             let semi: Option<Token![;]> = input.parse()?;
56             if semi.is_none() {
57                 let content;
58                 braced!(content in input);
59                 parse(&content, modules)?;
60             }
61         }
62     }
63     Ok(())
64 }
65 
parse_args(attr: &Attribute) -> Result<Namespace>66 fn parse_args(attr: &Attribute) -> Result<Namespace> {
67     if attr.tokens.is_empty() {
68         Ok(Namespace::ROOT)
69     } else {
70         attr.parse_args_with(Namespace::parse_bridge_attr_namespace)
71     }
72 }
73