aboutsummaryrefslogtreecommitdiff
path: root/gen/src/file.rs
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-08-29 14:07:38 -0700
committerDavid Tolnay <dtolnay@gmail.com>2020-08-29 14:36:42 -0700
commit3c64a4e144a4b7f476345e038212747fd6feb5c6 (patch)
tree4c462f103493b7ff2a8f31e060883d813e71e03c /gen/src/file.rs
parent17c3230d08481f23e7031ee8bd2ff59bba117837 (diff)
downloadcxx-3c64a4e144a4b7f476345e038212747fd6feb5c6.tar.gz
Parse full file using the new Module parser
Diffstat (limited to 'gen/src/file.rs')
-rw-r--r--gen/src/file.rs69
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()
}
}