diff options
author | David Tolnay <dtolnay@gmail.com> | 2020-08-29 14:07:38 -0700 |
---|---|---|
committer | David Tolnay <dtolnay@gmail.com> | 2020-08-29 14:36:42 -0700 |
commit | 3c64a4e144a4b7f476345e038212747fd6feb5c6 (patch) | |
tree | 4c462f103493b7ff2a8f31e060883d813e71e03c /gen/src/file.rs | |
parent | 17c3230d08481f23e7031ee8bd2ff59bba117837 (diff) | |
download | cxx-3c64a4e144a4b7f476345e038212747fd6feb5c6.tar.gz |
Parse full file using the new Module parser
Diffstat (limited to 'gen/src/file.rs')
-rw-r--r-- | gen/src/file.rs | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/gen/src/file.rs b/gen/src/file.rs index 3b45fe75..a2f86e69 100644 --- a/gen/src/file.rs +++ b/gen/src/file.rs @@ -1,20 +1,71 @@ -use syn::parse::{Parse, ParseStream, Result}; -use syn::{Attribute, Item}; +use crate::syntax::file::Module; +use crate::syntax::namespace::Namespace; +use syn::parse::discouraged::Speculative; +use syn::parse::{Error, Parse, ParseStream, Result}; +use syn::{braced, Attribute, Ident, Item, Token, Visibility}; pub struct File { - pub attrs: Vec<Attribute>, - pub items: Vec<Item>, + pub modules: Vec<Module>, } impl Parse for File { fn parse(input: ParseStream) -> Result<Self> { - let attrs = input.call(Attribute::parse_inner)?; + let mut modules = Vec::new(); + input.call(Attribute::parse_inner)?; + parse(input, &mut modules)?; + Ok(File { modules }) + } +} + +fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> { + while !input.is_empty() { + let mut cxx_bridge = false; + let mut namespace = Namespace::none(); + let attrs = input.call(Attribute::parse_outer)?; + for attr in &attrs { + let path = &attr.path.segments; + if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" { + cxx_bridge = true; + namespace = parse_args(attr)?; + break; + } + } - let mut items = Vec::new(); - while !input.is_empty() { - items.push(input.parse()?); + let ahead = input.fork(); + ahead.parse::<Visibility>()?; + ahead.parse::<Option<Token![unsafe]>>()?; + if !ahead.peek(Token![mod]) { + let item: Item = input.parse()?; + if cxx_bridge { + return Err(Error::new_spanned(item, "expected a module")); + } + continue; } - Ok(File { attrs, items }) + if cxx_bridge { + let mut module: Module = input.parse()?; + module.namespace = namespace; + module.attrs = attrs; + modules.push(module); + } else { + input.advance_to(&ahead); + input.parse::<Token![mod]>()?; + input.parse::<Ident>()?; + let semi: Option<Token![;]> = input.parse()?; + if semi.is_none() { + let content; + braced!(content in input); + parse(&content, modules)?; + } + } + } + Ok(()) +} + +fn parse_args(attr: &Attribute) -> Result<Namespace> { + if attr.tokens.is_empty() { + Ok(Namespace::none()) + } else { + attr.parse_args() } } |