From fb7df3b4b34f1c3781074b6fa0e07a66daf62596 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sun, 23 Jun 2019 22:40:10 +0200 Subject: [PATCH 1/3] [WIP] Move naming in backend, and deal with ASTs instead of flat structures. --- xml-schema/src/names.rs | 1 + xml-schema/src/parser_generator.rs | 454 +++++++++------------- xml-schema/src/processor.rs | 592 ++++++++++++----------------- 3 files changed, 432 insertions(+), 615 deletions(-) diff --git a/xml-schema/src/names.rs b/xml-schema/src/names.rs index e8e688a..e71d633 100644 --- a/xml-schema/src/names.rs +++ b/xml-schema/src/names.rs @@ -13,6 +13,7 @@ fn escape_keyword(name: &str) -> String { } } +#[derive(Debug)] pub(crate) struct NameGenerator(HashMap); impl NameGenerator { diff --git a/xml-schema/src/parser_generator.rs b/xml-schema/src/parser_generator.rs index ebed18a..1198d0d 100644 --- a/xml-schema/src/parser_generator.rs +++ b/xml-schema/src/parser_generator.rs @@ -21,6 +21,7 @@ impl<'input> ParseContext<'input> for XsdParseContext<'input> { } } +const MODULES_FOR_ANONYMOUS_SUBTYPES: &[&'static str] = &["enums", "unions", "inline_elements", "lists"]; const KEYWORDS: &[&'static str] = &["override"]; fn escape_keyword(name: &str) -> String { if KEYWORDS.contains(&name) { @@ -34,27 +35,33 @@ fn escape_keyword(name: &str) -> String { #[derive(Debug)] pub struct ParserGenerator<'ast, 'input: 'ast> { processors: Vec>, - module_names: HashMap, String>, // URI -> module name - primitive_types: HashMap<&'static str, RichType<'input, Type<'input>>>, - simple_restrictions: HashMap<(FullName<'input>, Facets<'input>), String>, + names: HashMap, (String, HashMap<&'input str, String>)>, // URI -> (module_name, element_name -> struct/enum name) + renames: HashMap, + name_gen: NameGenerator, + scope: cg::Scope, self_gen: bool, } impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { pub fn new(processors: Vec>, parse_context: &XsdParseContext<'input>, renames: HashMap) -> ParserGenerator<'ast, 'input> { - let mut module_names = HashMap::new(); - module_names.insert(None, "unqualified".to_string()); - let mut name_gen = NameGenerator::new(); + let mut names = HashMap::new(); + names.insert(None, ("unqualified".to_string(), HashMap::new())); + let mut module_name_gen = NameGenerator::new(); + + for &mod_name in MODULES_FOR_ANONYMOUS_SUBTYPES { + module_name_gen.gen_name(mod_name.to_string()); // Make sure the same names are not reused + } let mut primitive_types = HashMap::new(); for (name, type_name) in PRIMITIVE_TYPES { - primitive_types.insert(*name, RichType::new(NameHint::new(name), Type::Simple(SimpleType::Primitive(name, type_name)), Documentation::new())); + primitive_types.insert(*name, type_name.to_string()); } + names.insert(Some(SCHEMA_URI), (module_name_gen.gen_name("support".to_string()), primitive_types)); for (&uri, ns) in parse_context.namespaces.iter() { - if Some(&ns.to_string()) != module_names.get(&Some(uri)) { - module_names.insert(Some(uri), name_gen.gen_name(ns.to_string())); + if names.get(&Some(uri)).is_none() { + names.insert(Some(uri), (module_name_gen.gen_name(ns.to_string()), HashMap::new())); } } @@ -65,47 +72,41 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } ParserGenerator { - processors, renames, module_names, primitive_types, self_gen, - simple_restrictions: HashMap::new(), + processors, renames, names, self_gen, + name_gen: NameGenerator::new(), + scope: cg::Scope::new(), } } pub fn get_module_name(&self, qname: FullName<'input>) -> String { - if qname.namespace() == Some(SCHEMA_URI) { - for (name, _) in PRIMITIVE_TYPES { - if *name == qname.local_name() { - return "support".to_string(); - } - } - } - self.module_names.get(&qname.namespace()).expect(&format!("{:?}", qname.namespace())).clone() + self.names.get(&qname.namespace()).expect(&format!("{:?}", qname.namespace())).0.clone() } - pub fn gen_target_scope(&mut self) -> cg::Scope { - let mut scope = cg::Scope::new(); - scope.raw("pub use std::collections::HashMap;"); - scope.raw("pub use std::marker::PhantomData;"); - self.create_modules(&mut scope); - self.gen_choices(&mut scope); - self.gen_simple_types(&mut scope); - self.gen_lists(&mut scope); - self.gen_unions(&mut scope); - self.gen_sequences(&mut scope); - self.gen_elements(&mut scope); - self.gen_inline_elements(&mut scope); - self.gen_groups(&mut scope); - scope + pub fn gen_target_scope(&mut self) { + self.scope.raw("pub use std::collections::HashMap;"); + self.scope.raw("pub use std::marker::PhantomData;"); + self.create_modules(); + self.gen_elements(); + self.gen_inline_elements(); } - fn create_modules(&mut self, scope: &mut cg::Scope) { - let mut modules: Vec<_> = self.module_names.iter().collect(); - modules.sort(); - for (&uri, mod_name) in modules { + fn create_modules(&mut self) { + let mut modules: Vec<_> = self.names.iter().collect(); + modules.sort_by(|(ns1, _), (ns2, _)| ns1.cmp(ns2)); + + for submod_name in MODULES_FOR_ANONYMOUS_SUBTYPES { + let submod_name = self.name_gen.gen_name(submod_name.to_string()); // This will always return the name as-is; we're only doing this to avoid duplicates + let submod = self.scope.new_module(&submod_name); + submod.vis("pub"); + submod.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + } + + for (&uri, (mod_name, _type_names)) in modules { if !self.self_gen && uri == Some(SCHEMA_URI) { - scope.raw(&format!("#[allow(unused_imports)]\npub use xml_schema::parser::xs as {};", mod_name)); + self.scope.raw(&format!("#[allow(unused_imports)]\npub use xml_schema::parser::xs as {};", mod_name)); } else { - let mut module = scope.new_module(mod_name); + let mut module = self.scope.new_module(mod_name); module.vis("pub"); module.scope().raw(&format!("//! {:?}", uri)); module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); @@ -113,29 +114,31 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_choices(&self, scope: &mut cg::Scope) { - let module = scope.new_module("enums"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut choices: Vec<_> = proc.choices.iter().collect(); - choices.sort_by_key(|&(t,names)| (t, names.iter().collect::>())); - for (ref choice, ref names) in choices { - for name in names.iter() { - let enum_name = escape_keyword(&name.to_camel_case()); - let enum_name = name_gen.gen_name(enum_name); - self.gen_choice(module.scope(), &enum_name, choice, &Documentation::new()); - } - } + fn gen_complex_type(&mut self, node: &RichAstNode<'input, Type<'input>, ()>) -> Option<(String, String)> { + let RichAstNode { attrs, type_, doc, _data } = node; + match type_ { + Type::Choice(items) => self.gen_choice(items, doc), + Type::Sequence(items) => self.gen_group_or_sequence(items, doc), + _ => unimplemented!("{:?}", type_), } } - fn gen_choice(&self, scope: &mut cg::Scope, enum_name: &String, items: &Vec>>, doc: &Documentation<'input>) { - let mut impl_code = Vec::new(); + + fn gen_choice(&mut self, items: &Vec, ()>>, doc: &Documentation<'input>) { + let items: Vec<_> = items.iter().filter_map(|item| self.gen_complex_type(item)).collect(); + let mut name_hint = NameHint::new("choice"); + for item in items { + name_hint.extend(item.1); + } + let name = name_from_hint(name_hint).unwrap(); + let enum_name = escape_keyword(&name.to_camel_case()); + let enum_name = self.name_gen.gen_name(enum_name); let enum_name = self.renames.get(enum_name).unwrap_or(enum_name); + + let module = self.scope.get_module_mut("choices").unwrap(); + let mut impl_code = Vec::new(); impl_code.push(format!("impl_enum!({},", enum_name)); { - let enum_ = scope.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let enum_ = module.scope().new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); for (i, item) in items.iter().enumerate() { let mut fields = Vec::new(); let mut doc = doc.clone(); @@ -151,8 +154,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &item.type_); } enum_.doc(&doc.to_string()); - let variant_name = name_from_hint(&item.name_hint) - .unwrap_or(format!("{}{}", enum_name, i)).to_camel_case(); + let variant_name = item.1; let variant_name = escape_keyword(&variant_name.to_camel_case()); let variant_name = self.renames.get(&variant_name).unwrap_or(&variant_name); let mut variant = enum_.new_variant(&variant_name); @@ -196,93 +198,79 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } impl_code.push(");".to_string()); - scope.raw(&impl_code.join("\n")); + module.scope().raw(&impl_code.join("\n")); } - fn gen_unions(&self, scope: &mut cg::Scope) { - let module = scope.new_module("unions"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut unions: Vec<_> = proc.unions.iter().collect(); - unions.sort_by_key(|&(items, names)| (items, names.iter().collect::>())); - for (ref items, ref names) in unions { - for name in names.iter() { - let enum_name = escape_keyword(&name.to_camel_case()); - let enum_name = name_gen.gen_name(enum_name); - let mut impl_code = Vec::new(); - impl_code.push(format!("impl_union!({}, {{", enum_name)); - { - let enum_ = module.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - for item in items.iter() { - let RichType { name_hint, attrs, type_, doc } = item; - let variant_name = name_from_hint(name_hint).unwrap().to_camel_case(); - if let Some((type_mod_name, type_name)) = self.get_simple_type_name(type_) { - enum_.new_variant(&variant_name).tuple(&format!("{}::{}<'input>", type_mod_name, type_name)); - impl_code.push(format!(" impl_union_variant!({}),", variant_name)); - } - } - } - impl_code.push(format!("}});")); - module.scope().raw(&impl_code.join("\n")); + fn gen_union(&self, items: &Vec, ()>>, doc: &Documentation<'input>) { + let items: Vec<_> = items.iter().filter_map(|item| self.gen_simple_type(item)).collect(); + + let mut name_hint = NameHint::new("union"); + for item in items { + name_hint.extend(item.1); + } + let name = name_from_hint(name_hint); + let enum_name = escape_keyword(&name.to_camel_case()); + let enum_name = self.name_gen.gen_name(enum_name); + let enum_name = self.renames.get(enum_name).unwrap_or(enum_name); + + let module = self.scope.module_get_mut("unions").unwrap(); + let mut impl_code = Vec::new(); + impl_code.push(format!("impl_union!({}, {{", enum_name)); + { + let enum_ = module.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + if items.len() == 0 { + panic!("Union of the empty set.") // XXX Should we just return a None instead? + } + else if items.len() == 1 { + // Shortcut if this is a union for a single type + return items.get(0) + } + else { + let mut name_gen = NameGenerator::new(); + for (type_mod_name, type_name) in items { + let variant_name = name_gen.gen_name(type_name.to_camel_case()); + enum_.new_variant(&variant_name).tuple(&format!("{}::{}<'input>", type_mod_name, type_name)); + impl_code.push(format!(" impl_union_variant!({}),", variant_name)); } } } + impl_code.push(format!("}});")); + module.scope().raw(&impl_code.join("\n")); } - fn gen_lists(&self, scope: &mut cg::Scope) { - let module = scope.new_module("lists"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut lists: Vec<_> = proc.lists.iter().collect(); - lists.sort_by_key(|&(item_type, names)| (item_type, names.iter().collect::>())); - for (ref item_type, ref names) in lists { - for name in names.iter() { - let name = escape_keyword(&name.to_camel_case()); - let struct_name = name_gen.gen_name(name); - if let Some((type_mod_name, type_name)) = self.get_simple_type_name(&item_type.type_) { - { - let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); - } - module.scope().raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); - } - } - } + fn gen_list(&self, item: &RichAstNode<'input, SimpleType<'input>, ()>, doc: &Documentation<'input>) -> Option<(String, String)> { + if let Some((type_mod_name, type_name)) = self.gen_simple_type(item) { + let mut name = NameHint::new("list"); + name.extend(type_name.to_camel_case()); + let name = escape_keyword(&name); + let struct_name = self.name_gen.gen_name(name); + let module = self.scope.get_module_mut("structs").unwrap(); + let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); + module.scope().raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); + Some(("lists", struct_name)) + } + else { + None } } - fn get_simple_type_name(&self, ty: &SimpleType<'input>) -> Option<(String, String)> { - let (type_mod_name, type_name) = match ty { + fn gen_simple_type(&self, ty: &RichAstNode<'input, SimpleType<'input>, ()>) -> Option<(String, String)> { + let RichAstNode { attrs, type_, doc, data } = ty; + if attrs.named.len() != 0 || attrs.refs.len() != 0 || attrs.group_refs.len() != 0 || attrs.any_attributes { + // RichAstNode should be changed so impossibility is enforced by the type checker. + panic!("Simple type with attributes???"); + } + let (type_mod_name, type_name) = match type_ { SimpleType::Alias(name) => { - if name.namespace() == Some(&SCHEMA_URI) { - for (prim_name, prim_type_name) in PRIMITIVE_TYPES { - if *prim_name == name.local_name() { - return Some(("support".to_string(), prim_type_name.to_string())); - } - } - } - let type_mod_name = self.get_module_name(*name); - let type_mod_name = escape_keyword(&type_mod_name.to_snake_case()); - let type_name = escape_keyword(&name.local_name().to_camel_case()); + let (type_mod_name, local_names) = self.names.get(ty.namespace()) + .expect(&format!("Unknown namespace: {}", ty.namespace())); + let type_name = local_names.get(ty.local_name()) + .expect(&format!("Unknown type {} in namespace {}", ty.local_name(), ty.namespace())); (type_mod_name, type_name) }, - SimpleType::Restriction(name, facets) => { - ("restrictions".to_string(), self.simple_restrictions.get(&(name.clone(), facets.clone())).unwrap().to_string()) - } - SimpleType::Primitive(field_name, type_name) => { - ("support".to_string(), type_name.to_string()) - }, - SimpleType::Union(type_name) => { - let type_name = escape_keyword(&type_name.to_camel_case()); - ("unions".to_string(), type_name) - }, - SimpleType::List(name) => { - let type_name = escape_keyword(&name.to_camel_case()); - ("lists".to_string(), type_name) - }, + SimpleType::Restriction(name, facets) => self.gen_restriction(name, facets), + SimpleType::Union(items) => self.gen_union(items), + SimpleType::List(item) => self.gen_list(item), SimpleType::Empty => { return None }, @@ -290,128 +278,49 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { Some((type_mod_name, type_name)) } - fn gen_simple_types(&mut self, scope: &mut cg::Scope) { - self.gen_simple_restrictions(scope); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut types: Vec<_> = proc.simple_types.iter().collect(); - types.sort_by_key(|&(n,_)| n); - for (&qname, (ref ty, ref doc)) in types { - let mod_name = self.get_module_name(qname); - if mod_name == "support" { - // Implemented as a primitive, skip it. - continue; - } - let scope = scope.get_module_mut(&mod_name) - .expect(&mod_name).scope(); - let name = escape_keyword(&qname.local_name().to_camel_case()); - let name = name_gen.gen_name(name); - if let Some((type_mod_name, type_name)) = self.get_simple_type_name(&ty.type_) { - scope.raw(&format!("pub type {}<'input> = {}::{}<'input>;", name, type_mod_name, type_name)); + fn gen_simple_restriction(&mut self, base_name: FullName<'input>, facets: &Facets<'input>) { + let name = match &facets.enumeration { + Some(items) => { + if items.len() == 1 { + format!("{}", items[0]) } else { - panic!("{:?}", ty) - } - } - } - } - - fn gen_simple_restrictions(&mut self, scope: &mut cg::Scope) { - let mut name_gen = NameGenerator::new(); - let module = scope.new_module("restrictions"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - - for proc in &self.processors { - let mut simple_restrictions: Vec<_> = proc.simple_restrictions.iter().collect(); - - simple_restrictions.sort(); - for (base_name, facets) in simple_restrictions { - if self.simple_restrictions.get(&(*base_name, facets.clone())).is_some() { - continue; - } - let name = match &facets.enumeration { - Some(items) => { - if items.len() == 1 { - format!("{}", items[0]) - } - else { - format!("enumeration_{}", items.join("_")) - } - }, - None => format!("Restrict_{}", base_name.local_name()), - }; - let name = name.to_camel_case(); - let name = name_gen.gen_name(name.clone()); - self.simple_restrictions.insert((base_name.clone(), facets.clone()), name.clone()); - let (base_mod_name, base_type_name) = self.get_simple_type_name(&SimpleType::Alias(*base_name)).unwrap(); // TODO - module.scope().raw(&format!("#[derive(Debug, PartialEq)] pub struct {}<'input>(pub {}::{}<'input>);", name, base_mod_name, base_type_name)); - let mut s = Vec::new(); - let f = &mut |n: &Option<_>| { - match n.as_ref() { - None => "None".to_string(), - Some(f) => format!("Some(BigFloatNotNaN::from_str(\"{}\").unwrap())", f), - } - }; - s.push(format!("min_exclusive: {},", f(&facets.min_exclusive))); - s.push(format!("min_inclusive: {},", f(&facets.min_inclusive))); - s.push(format!("max_exclusive: {},", f(&facets.max_exclusive))); - s.push(format!("max_inclusive: {},", f(&facets.max_inclusive))); - s.push(format!("total_digits: {:?},", facets.total_digits)); - s.push(format!("fraction_digits: {:?},", facets.fraction_digits)); - s.push(format!("length: {:?},", facets.length)); - s.push(format!("min_length: {:?},", facets.min_length)); - s.push(format!("max_length: {:?},", facets.max_length)); - match &facets.enumeration { - Some(items) => s.push(format!("enumeration: Some(vec![{}]),", items.iter().map(|i| format!("{:?}", i)).collect::>().join(", "))), - None => s.push("enumeration: None,".to_string()), - } - s.push(format!("white_space: {:?},", facets.white_space)); - s.push(format!("pattern: {:?},", facets.pattern)); - s.push(format!("assertion: {:?},", facets.assertion)); - s.push(format!("explicit_timezone: {:?},", facets.explicit_timezone)); - module.scope().raw(&format!("impl_simpletype_restriction!({}, Facets {{\n {}\n}});", name, s.join("\n "))); - } - } - } - - fn gen_sequences(&mut self, scope: &mut cg::Scope) { - let module = scope.new_module("sequences"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - - for proc in &self.processors { - let mut sequences: Vec<_> = proc.sequences.iter().collect(); - - sequences.sort_by_key(|&(i,(n,_))| (n.iter().collect::>(), i)); - for (sequence, (names, doc)) in sequences { - for name in names.iter() { - self.gen_group_or_sequence(module, name, &sequence.iter().collect(), doc); - } - } - } - } - - fn gen_groups(&mut self, scope: &mut cg::Scope) { - for proc in &self.processors { - let mut groups: Vec<_> = proc.groups.iter().collect(); - - groups.sort_by_key(|&(n,_)| n); - for (&name, group) in groups { - let mod_name = self.get_module_name(name); - let mut module = scope.get_module_mut(&mod_name).unwrap(); - let struct_name = name.local_name(); - if let Type::InlineChoice(ref items) = group.type_ { - self.gen_choice(module.scope(), &struct_name.to_string().to_camel_case(), items, &group.doc); - } - else if let Type::InlineSequence(ref items) = group.type_ { - self.gen_group_or_sequence(module, struct_name, &items.iter().collect(), &group.doc); - } - else { - self.gen_group_or_sequence(module, struct_name, &vec![group], &group.doc); + format!("enumeration_{}", items.join("_")) } + }, + None => format!("Restrict_{}", base_name.local_name()), + }; + let name = name.to_camel_case(); + let name = self.name_gen.gen_name(name.clone()); + self.simple_restrictions.insert((base_name.clone(), facets.clone()), name.clone()); + let (base_mod_name, base_type_name) = self.get_simple_type_name(&SimpleType::Alias(*base_name)).unwrap(); // TODO + let mut module = self.scope.get_module_mut("enumerations").unwrap(); + module.scope().raw(&format!("#[derive(Debug, PartialEq)] pub struct {}<'input>(pub {}::{}<'input>);", name, base_mod_name, base_type_name)); + let mut s = Vec::new(); + let f = &mut |n: &Option<_>| { + match n.as_ref() { + None => "None".to_string(), + Some(f) => format!("Some(BigFloatNotNaN::from_str(\"{}\").unwrap())", f), } + }; + s.push(format!("min_exclusive: {},", f(&facets.min_exclusive))); + s.push(format!("min_inclusive: {},", f(&facets.min_inclusive))); + s.push(format!("max_exclusive: {},", f(&facets.max_exclusive))); + s.push(format!("max_inclusive: {},", f(&facets.max_inclusive))); + s.push(format!("total_digits: {:?},", facets.total_digits)); + s.push(format!("fraction_digits: {:?},", facets.fraction_digits)); + s.push(format!("length: {:?},", facets.length)); + s.push(format!("min_length: {:?},", facets.min_length)); + s.push(format!("max_length: {:?},", facets.max_length)); + match &facets.enumeration { + Some(items) => s.push(format!("enumeration: Some(vec![{}]),", items.iter().map(|i| format!("{:?}", i)).collect::>().join(", "))), + None => s.push("enumeration: None,".to_string()), } + s.push(format!("white_space: {:?},", facets.white_space)); + s.push(format!("pattern: {:?},", facets.pattern)); + s.push(format!("assertion: {:?},", facets.assertion)); + s.push(format!("explicit_timezone: {:?},", facets.explicit_timezone)); + module.scope().raw(&format!("impl_simpletype_restriction!({}, Facets {{\n {}\n}});", name, s.join("\n "))); } fn gen_fields(&self, empty_struct: &mut bool, struct_: &mut cg::Struct, impl_code: &mut Vec, doc: &mut Documentation<'input>, name_gen: &mut NameGenerator, type_: &Type<'input>) { @@ -445,10 +354,25 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &type_); } - fn gen_group_or_sequence(&self, module: &mut cg::Module, struct_name: &'input str, items: &Vec<&RichType<'input, Type<'input>>>, doc: &Documentation<'input>) { - let mut impl_code = Vec::new(); + fn gen_sequence(&mut self, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + self.gen_group_or_sequence("sequence", NameHint::new("sequence"), items, doc) + } + fn gen_group(&mut self, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + self.gen_group_or_sequence("group", NameHint::new("group"), items, doc) + } + fn gen_group_or_sequence(&mut self, mod_name: &str, name_hint: &NameHint<'input>, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + let items: Vec<_> = items.iter().filter_map(|item| self.gen_simple_type(item)).collect(); + + for item in items { + name_hint.extend(item.1); + } + let struct_name = name_from_hint(name_hint); let struct_name = escape_keyword(&struct_name.to_camel_case()); + let struct_name = self.name_gen.gen_name(struct_name); let struct_name = self.renames.get(&struct_name).unwrap_or(&struct_name); + + let mut module = self.scope.module_get_mut(mod_name).unwrap(); + let mut impl_code = Vec::new(); impl_code.push(format!("impl_group_or_sequence!({},", struct_name)); { let mut empty_struct = true; @@ -469,8 +393,8 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { module.scope().raw(&impl_code.join("\n")); } - fn gen_inline_elements(&mut self, scope: &mut cg::Scope) { - let module = scope.new_module("inline_elements"); + fn gen_inline_elements(&mut self) { + let module = self.scope.new_module("inline_elements"); module.vis("pub"); module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); for proc in &self.processors { @@ -494,14 +418,14 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_elements(&mut self, scope: &mut cg::Scope) { + fn gen_elements(&mut self) { for proc in &self.processors { let mut elements: Vec<_> = proc.elements.iter().collect(); elements.sort_by_key(|&(n,_)| n); for (&name, element) in elements { let mod_name = self.get_module_name(name); - let mut module = scope.get_module_mut(&mod_name).expect(&mod_name); + let mut module = self.scope.get_module_mut(&mod_name).expect(&mod_name); let head_local_name = format!("{}_head", name.local_name()); let mut substitutions = Vec::new(); substitutions.push(FullName::new(name.namespace(), &head_local_name)); @@ -524,12 +448,12 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_substitution_enum(&self, scope: &mut cg::Scope, enum_name: &str, substitutions: &Vec>) { + fn gen_substitution_enum(&self, enum_name: &str, substitutions: &Vec>) { let mut impl_code = Vec::new(); impl_code.push(format!("impl_enum!({},", enum_name)); let mut name_gen = NameGenerator::new(); { - let enum_ = scope.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let enum_ = self.scope.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); for &substitution in substitutions { let variant_name = escape_keyword(&name_gen.gen_name(substitution.local_name().to_camel_case())); let type_mod_name = escape_keyword(&self.get_module_name(substitution).to_snake_case()); @@ -540,7 +464,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } impl_code.push(");".to_string()); } - scope.raw(&impl_code.join("\n")); + self.scope.raw(&impl_code.join("\n")); } fn gen_attrs(&self, struct_: &mut cg::Struct, impl_code: &mut Vec, name_gen: &mut NameGenerator, attrs: &Attrs<'input>, seen_attrs: &mut HashMap, AttrUse>, generated_attrs: &mut HashSet>, inherited: bool) { @@ -561,12 +485,12 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { generated_attrs.insert(attr_name.clone()); match use_ { AttrUse::Optional => { - let field_name = name_gen.gen_name(format!("attr_{}", attr_name.local_name()).to_snake_case()); + let field_name = self.name_gen.gen_name(format!("attr_{}", attr_name.local_name()).to_snake_case()); struct_.field(&format!("pub {}", field_name), &format!("Option<{}::{}<'input>>", type_mod_name, type_name)); impl_code.push(format!(" ({:?}, {:?}) => {}: optional,", attr_name.namespace().unwrap_or(""), attr_name.local_name(), field_name)); }, AttrUse::Required => { - let field_name = name_gen.gen_name(format!("attr_{}", attr_name.local_name()).to_snake_case()); + let field_name = self.name_gen.gen_name(format!("attr_{}", attr_name.local_name()).to_snake_case()); struct_.field(&format!("pub {}", field_name), &format!("{}::{}<'input>", type_mod_name, type_name)); impl_code.push(format!(" ({:?}, {:?}) => {}: required,", attr_name.namespace().unwrap_or(""), attr_name.local_name(), field_name)); }, @@ -616,10 +540,10 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { module.scope().raw(&impl_code.join("\n")); } - fn get_type(&self, name: &FullName<'input>) -> &RichType<'input, Type<'input>> { + fn get_type_generated_name(&self, name: &FullName<'input>) -> (&str, str) { if name.namespace() == Some(SCHEMA_URI) { - if let Some(type_) = self.primitive_types.get(name.local_name()) { - return type_; + if let Some(name) = self.primitive_types.get(name.local_name()) { + return name; } } let mut type_ = None; diff --git a/xml-schema/src/processor.rs b/xml-schema/src/processor.rs index b433294..f163810 100644 --- a/xml-schema/src/processor.rs +++ b/xml-schema/src/processor.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; use std::hash::Hash; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use xmlparser::Token as XmlToken; use xmlparser::{TextUnescape, XmlSpace}; @@ -59,7 +59,7 @@ pub enum AttrUse { Optional, } -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Attrs<'input> { pub named: Vec<(FullName<'input>, AttrUse, Option>)>, pub refs: Vec<(Option>, AttrUse, FullName<'input>)>, @@ -80,55 +80,81 @@ impl<'input> Attrs<'input> { } #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct RichType<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord> { - pub name_hint: NameHint<'input>, +pub struct RichAstNode<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { pub attrs: Attrs<'input>, pub type_: T, pub doc: Documentation<'input>, + pub data: D, } -impl<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord> RichType<'input, T> { - pub fn new(name_hint: NameHint<'input>, type_: T, doc: Documentation<'input>) -> RichType<'input, T> { - RichType { name_hint, attrs: Attrs::new(), type_, doc } +impl<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, T, D> { + pub fn new(type_: T, doc: Documentation<'input>) -> RichAstNode<'input, T, D> { + RichAstNode { attrs: Attrs::new(), type_, doc, data: D::default() } } } -impl<'input> RichType<'input, Type<'input>> { - fn add_attrs(mut self, new_attrs: Attrs<'input>) -> RichType<'input, Type<'input>> { +impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, Type<'input>, D> { + fn add_attrs(mut self, new_attrs: Attrs<'input>) -> RichAstNode<'input, Type<'input>, D> { self.attrs.extend(new_attrs); self } } -impl<'input> RichType<'input, SimpleType<'input>> { - pub fn into_complex(self) -> RichType<'input, Type<'input>> { - let RichType { name_hint, attrs, type_, doc } = self; - RichType { name_hint, attrs, type_: Type::Simple(type_), doc } +impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, SimpleType<'input>, D> { + pub fn into_complex(self) -> RichAstNode<'input, Type<'input>, D> { + let RichAstNode { attrs, type_, doc, data } = self; + RichAstNode { attrs, type_: Type::Simple(type_), doc, data } + } +} + +/// A reference to a type, that can be part of another type/element/... +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct InlineComplexType<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { + min_occurs: usize, + max_occurs: usize, + type_: RichAstNode<'input, Type<'input>, D>, +} +impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineComplexType<'input, D> { + fn new(min_occurs: usize, max_occurs: usize, type_: RichAstNode<'input, Type<'input>, D>) -> InlineComplexType<'input, D> { + InlineComplexType { min_occurs, max_occurs, type_ } } } +/// A reference to a type, that can be part of another type/element/... +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct InlineSimpleType<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { + type_: RichAstNode<'input, SimpleType<'input>, D>, +} +impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineSimpleType<'input, D> { + fn new(type_: RichAstNode<'input, SimpleType<'input>, D>) -> InlineSimpleType<'input, D> { + InlineSimpleType { type_ } + } + + fn into_complex(self) -> InlineComplexType<'input, D> { + InlineComplexType { min_occurs: 0, max_occurs: 0, type_: self.type_.into_complex() } + } +} + + #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Type<'input> { Any, Empty, Alias(FullName<'input>), - Extension(FullName<'input>, Box>>), - Restriction(FullName<'input>, Box>>), - ElementRef(usize, usize, FullName<'input>), - Element(usize, usize, String), - Group(usize, usize, FullName<'input>), - Choice(usize, usize, String), - InlineChoice(Vec>>), - Sequence(usize, usize, String), - InlineSequence(Vec>>), + Extension(FullName<'input>, Box>), + Restriction(FullName<'input>, Box>), + ElementRef(FullName<'input>), + Element(FullName<'input>), + Group(FullName<'input>), + Choice(Vec>), + Sequence(Vec>), Simple(SimpleType<'input>), } -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum SimpleType<'input> { - Primitive(&'static str, &'static str), Alias(FullName<'input>), Restriction(FullName<'input>, Facets<'input>), - List(String), - Union(String), + List(Box>), + Union(Vec>), Empty, } @@ -137,18 +163,11 @@ pub struct Processor<'ast, 'input: 'ast> { pub target_namespace: Option<&'input str>, pub element_form_default_qualified: bool, pub attribute_form_default_qualified: bool, - pub elements: HashMap, RichType<'input, Type<'input>>>, - pub types: HashMap, RichType<'input, Type<'input>>>, - pub simple_types: HashMap, (RichType<'input, SimpleType<'input>>, Documentation<'input>)>, - pub choices: HashMap>>, HashSet>, - pub sequences: HashMap>>, (HashSet, Documentation<'input>)>, - pub groups: HashMap, RichType<'input, Type<'input>>>, + pub elements: HashMap, InlineComplexType<'input, ()>>, + pub simple_types: HashMap, (InlineSimpleType<'input, ()>, Documentation<'input>)>, + pub groups: HashMap, InlineComplexType<'input, ()>>, pub attribute_groups: HashMap, Attrs<'input>>, - pub inline_elements: HashMap<(Option<&'input str>, &'input str, Attrs<'input>, Type<'input>), (HashSet, Documentation<'input>)>, - pub lists: HashMap>, HashSet>, - pub unions: HashMap>>, HashSet>, - pub simple_restrictions: HashSet<(FullName<'input>, Facets<'input>)>, pub substitution_groups: HashMap, Vec>>, _phantom: PhantomData<&'ast ()>, // Sometimes I need 'ast when prototyping } @@ -171,16 +190,9 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { element_form_default_qualified, attribute_form_default_qualified, elements: HashMap::new(), - types: HashMap::new(), groups: HashMap::new(), - choices: HashMap::new(), - lists: HashMap::new(), - unions: HashMap::new(), - sequences: HashMap::new(), attribute_groups: HashMap::new(), - inline_elements: HashMap::new(), simple_types: HashMap::new(), - simple_restrictions: HashSet::new(), substitution_groups: HashMap::new(), _phantom: PhantomData::default(), } @@ -189,7 +201,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { pub fn process_ast(&mut self, ast: &'ast xs::Schema<'input>) { for top_level_item in ast.sequence_schema_top_annotation.iter() { match top_level_item.schema_top { - xs::SchemaTop::Redefinable(ref r) => self.process_redefinable(r, false), + xs::SchemaTop::Redefinable(ref r) => self.process_redefinable(r), xs::SchemaTop::Element(ref e) => { self.process_toplevel_element(e); }, xs::SchemaTop::Attribute(_) => unimplemented!("top-level attribute"), xs::SchemaTop::Notation(ref e) => self.process_notation(e), @@ -201,10 +213,10 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { // TODO } - fn process_redefinable(&mut self, r: &'ast xs::Redefinable<'input>, inlinable: bool) { + fn process_redefinable(&mut self, r: &'ast xs::Redefinable<'input>) { match r { xs::Redefinable::SimpleType(ref e) => { self.process_simple_type(e); }, - xs::Redefinable::ComplexType(e) => { self.process_complex_type(e, inlinable); }, + xs::Redefinable::ComplexType(e) => { self.process_complex_type(e); }, xs::Redefinable::Group(e) => { self.process_named_group(e); }, xs::Redefinable::AttributeGroup(e) => self.process_attribute_group(e), } @@ -234,44 +246,38 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_group_ref(&mut self, group_ref: &'ast inline_elements::GroupRef<'input>, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let inline_elements::GroupRef { ref attrs, ref attr_id, ref attr_ref, ref attr_min_occurs, ref attr_max_occurs, ref annotation } = group_ref; let ref_ = attr_ref; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); let ref_ = FullName::from_qname(ref_, self.target_namespace); - RichType::new( - NameHint::new(ref_.local_name()), - Type::Group(min_occurs, max_occurs, ref_), - self.process_annotation(&annotation.iter().collect()), - ) + + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Group(ref_), + self.process_annotation(&annotation.iter().collect()), + )) } fn process_named_group(&mut self, group: &'ast xs::Group<'input>, - ) -> RichType<'input, Type<'input>> { + ) { let xs::Group { ref attrs, ref attr_id, ref attr_name, ref annotation, choice_all_choice_sequence: ref content } = group; let name = attr_name; - let max_occurs = 1; - let min_occurs = 1; let mut type_ = match content { enums::ChoiceAllChoiceSequence::All(_) => unimplemented!("all"), - enums::ChoiceAllChoiceSequence::Choice(e) => self.process_choice(e, true), - enums::ChoiceAllChoiceSequence::Sequence(e) => self.process_sequence(e, true), + enums::ChoiceAllChoiceSequence::Choice(e) => self.process_choice(e), + enums::ChoiceAllChoiceSequence::Sequence(e) => self.process_sequence(e), }; - type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); - let doc = type_.doc.clone(); + type_.type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); let name = FullName::new(self.target_namespace, name.0); self.groups.insert(name, type_); - RichType::new( - NameHint::from_fullname(&name), - Type::Group(min_occurs, max_occurs, name), - doc, - ) } fn process_attribute_group(&mut self, group: &'ast xs::AttributeGroup<'input>) { @@ -283,7 +289,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_local_simple_type(&mut self, simple_type: &'ast inline_elements::LocalSimpleType<'input>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> InlineSimpleType<'input, ()> { let inline_elements::LocalSimpleType { ref attrs, ref attr_id, ref annotation, ref simple_derivation } = simple_type; //let struct_name = self.namespaces.new_type(QName::from(name)); let annotation: Vec<_> = annotation.iter().collect(); @@ -296,7 +302,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_simple_type(&mut self, simple_type: &'ast xs::SimpleType<'input>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> InlineSimpleType<'input, ()> { let xs::SimpleType { ref attrs, ref attr_id, ref attr_name, ref attr_final, ref annotation, ref simple_derivation } = simple_type; let annotation: Vec<_> = annotation.iter().collect(); let name = attr_name; @@ -311,143 +317,106 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { let doc = self.process_annotation(&annotation); self.simple_types.insert(name, (ty, doc.clone())); - RichType::new( - NameHint::from_fullname(&name), - SimpleType::Alias(name), - doc, - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Alias(name), + doc, + )) } fn process_list(&mut self, list: &'ast xs::List<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> InlineSimpleType<'input, ()> { let item_type = list.attr_item_type; let item_type = item_type.as_ref().map(|n| FullName::from_qname(n, self.target_namespace)); let item_type = match (item_type, &list.local_simple_type) { (None, Some(st)) => { let mut ty = self.process_local_simple_type(st); - ty.doc.extend(&self.process_annotation(&annotation)); + ty.type_.doc.extend(&self.process_annotation(&annotation)); ty }, (Some(n), None) => { - RichType::new( - NameHint::new(n.local_name()), - SimpleType::Alias(n), - self.process_annotation(&annotation), - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Alias(n), + self.process_annotation(&annotation), + )) }, (None, None) => panic!(" with no itemType or child type."), (Some(ref t1), Some(ref t2)) => panic!(" has both an itemType attribute ({:?}) and a child type ({:?}).", t1, t2), }; - let mut name_hint = item_type.name_hint.clone(); - name_hint.push("list"); let doc = self.process_annotation(&annotation); - let name = name_from_hint(&name_hint).unwrap(); - self.lists.entry(item_type) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( - name_hint, - SimpleType::List(name), - doc, - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::List(Box::new(item_type)), + doc, + )) } fn process_union(&mut self, union: &'ast xs::Union<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> InlineSimpleType<'input, ()> { let default_vec = Vec::new(); - let mut name_hint = NameHint::new("union"); let member_types = union.attr_member_types.as_ref().map(|l| &l.0).unwrap_or(&default_vec); let mut member_types: Vec<_> = member_types.iter().map(|name| { let name = FullName::from_qname(name, self.target_namespace); - name_hint.push(name.local_name()); - RichType::new( - NameHint::new(name.local_name()), - SimpleType::Alias(name), - self.process_annotation(&annotation), - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Alias(name), + self.process_annotation(&annotation), + )) }).collect(); for t in union.local_simple_type.iter() { let ty = self.process_local_simple_type(t); - name_hint.extend(&ty.name_hint); member_types.push(ty) } let doc = self.process_annotation(&annotation); - let name = name_from_hint(&name_hint).unwrap(); - self.unions.entry(member_types) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( - name_hint, - SimpleType::Union(name), - doc, - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Union(member_types), + doc, + )) } fn process_complex_type(&mut self, complex_type: &'ast xs::ComplexType<'input>, - inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let xs::ComplexType { ref attrs, ref attr_id, ref attr_name, ref attr_mixed, ref attr_abstract, ref attr_final, ref attr_block, ref attr_default_attributes_apply, ref annotation, ref complex_type_model } = complex_type; let name = attr_name; //let struct_name = self.namespaces.new_type(QName::from(name)); let mut ty = match complex_type_model { xs::ComplexTypeModel::SimpleContent(_) => unimplemented!("simpleContent"), xs::ComplexTypeModel::ComplexContent(ref model) => - self.process_complex_content(model, false), + self.process_complex_content(model), xs::ComplexTypeModel::CompleteContentModel { ref open_content, ref type_def_particle, ref attr_decls, ref assertions } => - self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions, inlinable), + self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions), }; - ty.doc.extend(&self.process_annotation(&annotation.iter().collect())); - - let doc = ty.doc.clone(); - let name = FullName::new(self.target_namespace, name.0); - self.types.insert(name, ty); - RichType::new( - NameHint::from_fullname(&name), - Type::Alias(name), - doc, - ) + ty.type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); + ty } fn process_local_complex_type(&mut self, complex_type: &'ast inline_elements::LocalComplexType<'input>, attr_name: Option<&'ast NcName<'input>>, annotation: Vec<&'ast xs::Annotation<'input>>, - inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let inline_elements::LocalComplexType { ref attrs, ref attr_id, ref attr_mixed, ref attr_default_attributes_apply, annotation: ref annotation2, ref complex_type_model } = complex_type; let name = attr_name; - //let struct_name = self.namespaces.new_type(QName::from(name)); let mut ty = match complex_type_model { xs::ComplexTypeModel::SimpleContent(_) => unimplemented!("simpleContent"), xs::ComplexTypeModel::ComplexContent(ref model) => - self.process_complex_content(model, false), + self.process_complex_content(model), xs::ComplexTypeModel::CompleteContentModel { ref open_content, ref type_def_particle, ref attr_decls, ref assertions } => - self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions, inlinable), + self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions), }; - ty.doc.extend(&self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref()))); - - if let Some(name) = name { - let doc = ty.doc.clone(); - let name = FullName::new(self.target_namespace, name.0); - self.types.insert(name, ty); - RichType::new( - NameHint::from_fullname(&name), - Type::Alias(name), - doc, - ) - } - else { - ty - } + ty.type_.doc.extend(&self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref()))); + ty } fn process_complete_content_model(&mut self, @@ -455,20 +424,19 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { type_def_particle: &'ast Option>>, attr_decls: &'ast xs::AttrDecls<'input>, assertions: &'ast xs::Assertions<'input>, - inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let ty = match type_def_particle.as_ref() { - Some(type_def_particle) => self.process_type_def_particle(type_def_particle, inlinable), - None => RichType::new( - NameHint::new("empty_particle"), + Some(type_def_particle) => self.process_type_def_particle(type_def_particle), + None => InlineComplexType::new(1, 1, RichAstNode::new( Type::Empty, Documentation::new() - ), + )), }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + ty.type_.add_attrs(self.process_attr_decls(attr_decls)); + ty } - fn process_complex_content(&mut self, model: &'ast xs::ComplexContent<'input>, inlinable: bool) -> RichType<'input, Type<'input>> { + fn process_complex_content(&mut self, model: &'ast xs::ComplexContent<'input>) -> InlineComplexType<'input, ()> { let xs::ComplexContent { ref attrs, ref attr_id, ref attr_mixed, ref annotation, ref choice_restriction_extension } = model; let annotation = annotation.iter().collect(); match choice_restriction_extension { @@ -482,14 +450,16 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { Some(sequences::SequenceOpenContentTypeDefParticle { open_content, type_def_particle }) => self.process_complex_restriction(attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref())), None => { - RichType::new( - NameHint::new("empty_extension"), - Type::Empty, - self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Empty, + self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), + )) }, }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + ty.type_.add_attrs(self.process_attr_decls(attr_decls)); + ty }, enums::ChoiceRestrictionExtension::Extension(ref e) => { let inline_elements::ExtensionType { @@ -498,10 +468,11 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { } = **e; let ty = match type_def_particle { Some(type_def_particle) => - self.process_extension(attrs, attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref()), inlinable), + self.process_extension(attrs, attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref())), None => self.process_trivial_extension(attrs, attr_base, vec_concat_opt(&annotation, annotation2.as_ref())), }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + ty.type_.add_attrs(self.process_attr_decls(attr_decls)); + ty }, } } @@ -510,15 +481,16 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_base: &'ast QName<'input>, type_def_particle: &'ast xs::TypeDefParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { // TODO: use the base - let ty = self.process_type_def_particle(type_def_particle, false); + let ty = self.process_type_def_particle(type_def_particle); let base = FullName::from_qname(attr_base, self.target_namespace); - RichType::new( - NameHint::new_empty(), - Type::Restriction(base, Box::new(ty)), - self.process_annotation(&annotation), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Restriction(base, Box::new(ty)), + self.process_annotation(&annotation), + )) } fn process_facets(&mut self, facet_list: &Vec>) -> Facets<'input> { @@ -554,7 +526,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_simple_restriction(&mut self, restriction: &'ast xs::Restriction<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> InlineSimpleType<'input, ()> { let xs::Restriction { ref attrs, ref attr_id, ref attr_base, annotation: ref annotation2, ref simple_restriction_model } = restriction; let base = attr_base; let base = base.unwrap_or(QName { namespace: Some(SCHEMA_URI), local_name: "anySimpleType" }); @@ -563,182 +535,116 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { let base = FullName::from_qname(&base, self.target_namespace); - self.simple_restrictions.insert((base, facets.clone())); - match local_simple_type { Some(inline_elements::LocalSimpleType { ref attrs, ref attr_id, annotation: ref annotation2, ref simple_derivation }) => { - RichType::new( - NameHint::new(base.local_name()), - SimpleType::Restriction(base, facets), - self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Restriction(base, facets), + self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), + )) }, None => { - RichType::new( - NameHint::new(base.local_name()), - SimpleType::Restriction(base, facets), - self.process_annotation(&annotation), - ) + InlineSimpleType::new( + RichAstNode::new( + SimpleType::Restriction(base, facets), + self.process_annotation(&annotation), + )) }, } } - fn process_type_def_particle(&mut self, particle: &'ast xs::TypeDefParticle<'input>, inlinable: bool) -> RichType<'input, Type<'input>> { + fn process_type_def_particle(&mut self, particle: &'ast xs::TypeDefParticle<'input>) -> InlineComplexType<'input, ()> { match particle { xs::TypeDefParticle::Group(e) => self.process_group_ref(e), xs::TypeDefParticle::All(_) => unimplemented!("all"), - xs::TypeDefParticle::Choice(e) => self.process_choice(e, inlinable), - xs::TypeDefParticle::Sequence(e) => self.process_sequence(e, inlinable), + xs::TypeDefParticle::Choice(e) => self.process_choice(e), + xs::TypeDefParticle::Sequence(e) => self.process_sequence(e), } } fn process_nested_particle(&mut self, particle: &'ast xs::NestedParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - inlinable: bool - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let mut ty = match particle { xs::NestedParticle::Element(e) => self.process_local_element(e), xs::NestedParticle::Group(e) => self.process_group_ref(e), - xs::NestedParticle::Choice(e) => self.process_choice(e, inlinable), - xs::NestedParticle::Sequence(e) => self.process_sequence(e, inlinable), + xs::NestedParticle::Choice(e) => self.process_choice(e), + xs::NestedParticle::Sequence(e) => self.process_sequence(e), xs::NestedParticle::Any(e) => self.process_any(e, Vec::new()), }; - ty.doc.extend(&self.process_annotation(&annotation)); + ty.type_.doc.extend(&self.process_annotation(&annotation)); ty } fn process_any(&mut self, any: &'ast xs::Any<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { - RichType::new( - NameHint::new("any"), - Type::Any, - self.process_annotation(&annotation), - ) + ) -> InlineComplexType<'input, ()> { + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Any, + self.process_annotation(&annotation), + )) } fn process_sequence(&mut self, seq: &'ast xs::Sequence<'input>, - inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let xs::Sequence { ref attrs, ref attr_id, ref attr_min_occurs, ref attr_max_occurs, ref annotation, ref nested_particle } = seq; let particles = nested_particle; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); - let mut items = Vec::new(); - let mut name_hint = NameHint::new("sequence"); - if min_occurs == 1 && max_occurs == 1 && inlinable && particles.len() == 1 { - self.process_nested_particle(particles.get(0).unwrap(), annotation.iter().collect(), inlinable) + if min_occurs == 1 && max_occurs == 1 && particles.len() == 1 { + self.process_nested_particle(particles.get(0).unwrap(), annotation.iter().collect()) } else { - for particle in particles.iter() { - let ty = self.process_nested_particle(particle, vec![], false); - name_hint.extend(&ty.name_hint); - items.push(ty); - } + let items = particles.iter().map(|particle| + self.process_nested_particle(particle, vec![]) + ).collect(); let doc = self.process_annotation(&annotation.iter().collect()); - if min_occurs == 1 && max_occurs == 1 { - RichType::new( - name_hint, - Type::InlineSequence(items), - doc, - ) - } - else { - let name = name_from_hint(&name_hint).unwrap(); - let (names, docs) = self.sequences.entry(items) - .or_insert((HashSet::new(), Documentation::new())); - names.insert(name.clone()); - docs.extend(&doc); - RichType::new( - name_hint, - Type::Sequence(min_occurs, max_occurs, name), + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Sequence(items), doc, - ) - } + )) } } fn process_choice(&mut self, choice: &'ast xs::Choice<'input>, - inlinable: bool - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let xs::Choice { ref attrs, ref attr_id, ref attr_min_occurs, ref attr_max_occurs, ref annotation, ref nested_particle } = choice; let particles = nested_particle; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); - let mut items = Vec::new(); - let mut name_hint = NameHint::new("choice"); - if particles.len() == 1 { - let particle = particles.get(0).unwrap(); - let RichType { name_hint, attrs, type_, doc } = - self.process_nested_particle(particle, annotation.iter().collect(), inlinable); - match (min_occurs, max_occurs, type_) { - (_, _, Type::Element(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Element(min_occurs, max_occurs, e), doc }, - (_, _, Type::Group(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Group(min_occurs, max_occurs, e), doc }, - (_, _, Type::Choice(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Choice(min_occurs, max_occurs, e), doc }, - (_, _, Type::Sequence(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Sequence(min_occurs, max_occurs, e), doc }, - (1, 1, type_) => return RichType { name_hint, attrs, type_, doc }, - (_, _, type_) => { - let name = name_from_hint(&name_hint).unwrap(); - let items = vec![RichType { name_hint: name_hint.clone(), attrs: Attrs::new(), type_, doc: doc.clone() }]; - let (names, docs) = self.sequences.entry(items) - .or_insert((HashSet::new(), Documentation::new())); - names.insert(name.clone()); - docs.extend(&doc); - let type_ = Type::Sequence(min_occurs, max_occurs, name); - return RichType { name_hint, attrs, type_, doc } - }, - } - } - else { - for particle in particles.iter() { - let ty = self.process_nested_particle(particle, vec![], false); - name_hint.extend(&ty.name_hint); - items.push(ty); - } - } + let mut items = particles.iter().map(|particle| + self.process_nested_particle(particle, vec![]) + ).collect(); let doc = self.process_annotation(&annotation.iter().collect()); - match (min_occurs, max_occurs, inlinable) { - (1, 1, true) => { - RichType::new( - name_hint, - Type::InlineChoice(items), - doc, - ) - }, - (_, _, _) => { - let name = name_from_hint(&name_hint).unwrap(); - self.choices.entry(items) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( - name_hint, - Type::Choice(min_occurs, max_occurs, name), - doc, - ) - } - } + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Choice(items), + doc, + )) } fn process_trivial_extension(&mut self, attrs: &'ast HashMap, &'input str>, attr_base: &'ast QName<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let base = FullName::from_qname(&attr_base, self.target_namespace); - RichType::new( - NameHint::new_empty(), - Type::Alias(base), - self.process_annotation(&annotation), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Alias(base), + self.process_annotation(&annotation), + )) } fn process_extension(&mut self, @@ -746,14 +652,14 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_base: &'ast QName<'input>, type_def_particle: &'ast xs::TypeDefParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let base = FullName::from_qname(attr_base, self.target_namespace); - RichType::new( - NameHint::new_empty(), - Type::Extension(base, Box::new(self.process_type_def_particle(type_def_particle, inlinable))), - self.process_annotation(&annotation), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Extension(base, Box::new(self.process_type_def_particle(type_def_particle))), + self.process_annotation(&annotation), + )) } fn process_toplevel_element(&mut self, element: &'ast xs::Element<'input>) { @@ -774,27 +680,29 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { (None, Some(ref c)) => match c { enums::Type::SimpleType(ref e) => { let mut ty = self.process_local_simple_type(e); - ty.doc.extend(&self.process_annotation(&annotation)); + ty.type_.doc.extend(&self.process_annotation(&annotation)); ty.into_complex() }, enums::Type::ComplexType(ref e) => { - self.process_local_complex_type(e, Some(attr_name), annotation, false) + self.process_local_complex_type(e, Some(attr_name), annotation) }, }, (Some(t), None) => { let t = FullName::from_qname(&t, self.target_namespace); - RichType::new( - NameHint::new(t.local_name()), - Type::Alias(t.into()), - self.process_annotation(&annotation), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Alias(t.into()), + self.process_annotation(&annotation), + )) }, (None, None) => { - RichType::new( - NameHint::new("empty"), - Type::Empty, - self.process_annotation(&annotation), - ) + InlineComplexType::new( + 1, 1, + RichAstNode::new( + Type::Empty, + self.process_annotation(&annotation), + )) }, (Some(ref t1), Some(ref t2)) => panic!("Toplevel element '{:?}' has both a type attribute ({:?}) and a child type ({:?}).", name, t1, t2), }; @@ -804,7 +712,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_local_element(&mut self, element: &'ast inline_elements::LocalElement<'input>, - ) -> RichType<'input, Type<'input>> { + ) -> InlineComplexType<'input, ()> { let inline_elements::LocalElement { ref attrs, ref attr_id, ref attr_name, ref attr_ref, ref attr_min_occurs, ref attr_max_occurs, ref attr_type, ref attr_default, ref attr_fixed, ref attr_nillable, ref attr_block, ref attr_form, ref attr_target_namespace, ref annotation, ref type_, ref alternative_alt_type, ref identity_constraint } = element; let annotation = annotation.iter().collect(); let name = attr_name; @@ -817,11 +725,12 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { panic!(" has both ref={:?} and name={:?}", ref_, name); } let ref_ = FullName::from_qname(ref_, self.target_namespace); - RichType::new( - NameHint::new(ref_.local_name()), - Type::ElementRef(min_occurs, max_occurs, ref_), - self.process_annotation(&annotation), - ) + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::ElementRef(ref_), + self.process_annotation(&annotation), + )) } else { let name = name.as_ref().expect(" has no name.").0; @@ -839,61 +748,44 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { (None, false) => None, }; + let mut doc = self.process_annotation(&annotation); + match (type_attr, &type_) { (None, Some(ref c)) => { let mut t = match c { enums::Type::SimpleType(ref e) => { let mut ty = self.process_local_simple_type(e); - ty.doc.extend(&self.process_annotation(&annotation)); + ty.type_.doc.extend(&self.process_annotation(&annotation)); ty.into_complex() }, enums::Type::ComplexType(ref e) => { - self.process_local_complex_type(e, None, annotation, false) + self.process_local_complex_type(e, None, annotation) }, }; - let mut name_hint = NameHint::new(name); - name_hint.extend(&t.name_hint); - let struct_name = name_from_hint(&name_hint).unwrap(); - let (elems, doc) = self.inline_elements.entry((namespace, name, t.attrs, t.type_)) - .or_insert((HashSet::new(), Documentation::new())); - elems.insert(struct_name.clone()); - t.doc.extend(doc); - RichType::new( - NameHint::new(name), - Type::Element(min_occurs, max_occurs, struct_name), - t.doc, - ) + t.type_.doc.extend(&doc); + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Element(FullName::new(namespace, name)), + t.type_.doc.clone(), + )) }, (Some(t), None) => { - let name_hint1 = NameHint::new(t.local_name); - let mut name_hint2 = NameHint::new(name); - name_hint2.push(t.local_name); - // TODO: move this heuristic in names.rs - let name_hint = if t.local_name.to_lowercase().contains(&name.to_lowercase()) { - name_hint1 - } - else { - name_hint2 - }; - let struct_name = name_from_hint(&name_hint).unwrap(); - let mut doc = self.process_annotation(&annotation); - let t = FullName::from_qname(t, self.target_namespace); - let (elems, doc2) = self.inline_elements.entry((namespace, name, Attrs::new(), Type::Alias(t))) - .or_insert((HashSet::new(), Documentation::new())); - elems.insert(struct_name.clone()); - doc.extend(doc2); - RichType::new( - NameHint::new(name), - Type::Element(min_occurs, max_occurs, struct_name), - doc, - ) + let name = FullName::from_qname(t, self.target_namespace); + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Element(name), + doc, + )) }, (None, None) => { - RichType::new( - NameHint::new("empty"), - Type::Empty, - self.process_annotation(&annotation), - ) + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Empty, + self.process_annotation(&annotation), + )) }, (Some(ref t1), Some(ref t2)) => panic!("Element '{:?}' has both a type attribute ({:?}) and a child type ({:?}).", name, t1, t2), } @@ -921,7 +813,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { }, (Some(name), None, None, Some(t)) => { let t = self.process_local_simple_type(t); - attrs.named.push((name, use_, Some(t.type_))); + attrs.named.push((name, use_, Some(t.type_.type_))); }, (Some(name), None, None, None) => attrs.named.push((name, use_, None)), From 153d00c533f8c3a36aa928c33668826282b83423 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sun, 30 Jun 2019 17:17:12 +0200 Subject: [PATCH 2/3] [WIP] progress --- xml-schema/src/parser_generator.rs | 118 ++++++++++++++++------------- xml-schema/src/processor.rs | 7 +- 2 files changed, 70 insertions(+), 55 deletions(-) diff --git a/xml-schema/src/parser_generator.rs b/xml-schema/src/parser_generator.rs index 1198d0d..35bc300 100644 --- a/xml-schema/src/parser_generator.rs +++ b/xml-schema/src/parser_generator.rs @@ -115,51 +115,54 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } fn gen_complex_type(&mut self, node: &RichAstNode<'input, Type<'input>, ()>) -> Option<(String, String)> { - let RichAstNode { attrs, type_, doc, _data } = node; + let RichAstNode { attrs, type_, doc, data: _ } = node; match type_ { Type::Choice(items) => self.gen_choice(items, doc), - Type::Sequence(items) => self.gen_group_or_sequence(items, doc), + Type::Sequence(items) => self.gen_sequence(items, doc), _ => unimplemented!("{:?}", type_), } } - fn gen_choice(&mut self, items: &Vec, ()>>, doc: &Documentation<'input>) { - let items: Vec<_> = items.iter().filter_map(|item| self.gen_complex_type(item)).collect(); + fn gen_choice(&mut self, items: &Vec>>, doc: &Documentation<'input>) -> Option<(String, String)> { + let items: Vec> = items.iter().map( + |variants| variants.iter().filter_map( + |InlineComplexType { min_occurs, max_occurs, type_ }| + self.gen_complex_type(type_).map(|item| (min_occurs, max_occurs, item)) + ).collect() + ).collect(); let mut name_hint = NameHint::new("choice"); - for item in items { - name_hint.extend(item.1); + for variant in items { + for (_min_occurs, _max_occurs, field) in variant { + name_hint.push(&field.1); + } } - let name = name_from_hint(name_hint).unwrap(); + let name = name_from_hint(&name_hint).unwrap(); let enum_name = escape_keyword(&name.to_camel_case()); let enum_name = self.name_gen.gen_name(enum_name); - let enum_name = self.renames.get(enum_name).unwrap_or(enum_name); + let enum_name = self.renames.get(&enum_name).unwrap_or(&enum_name); + + let mut variant_name_gen = NameGenerator::new(); let module = self.scope.get_module_mut("choices").unwrap(); let mut impl_code = Vec::new(); impl_code.push(format!("impl_enum!({},", enum_name)); { let enum_ = module.scope().new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - for (i, item) in items.iter().enumerate() { - let mut fields = Vec::new(); + for (i, fields) in items.iter().enumerate() { + // TODO: handle min_occurs and max_occurs let mut doc = doc.clone(); - { - let mut name_gen = NameGenerator::new(); - let field_writer = &mut |field_name: String, type_mod_name: String, min_occurs, max_occurs, type_name: String| { - let field_name = escape_keyword(&name_gen.gen_name(field_name.to_snake_case())); - let type_mod_name = escape_keyword(&type_mod_name.to_snake_case()); - let type_name = escape_keyword(&type_name.to_camel_case()); - fields.push((field_name, type_mod_name, min_occurs, max_occurs, type_name)); - }; - let doc_writer = &mut |doc2: &Documentation<'input>| doc.extend(doc2); - self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &item.type_); + let variant_name = NameHint::new_empty(); + for (_min_occurs, _max_occurs, (_mod_name, field_type_name)) in fields.iter() { + variant_name.push(&field_type_name); } - enum_.doc(&doc.to_string()); - let variant_name = item.1; + let variant_name = name_from_hint(&variant_name).unwrap(); // TODO: handle fields.len()==0 let variant_name = escape_keyword(&variant_name.to_camel_case()); + let variant_name = variant_name_gen.gen_name(variant_name); let variant_name = self.renames.get(&variant_name).unwrap_or(&variant_name); let mut variant = enum_.new_variant(&variant_name); + enum_.doc(&doc.to_string()); // TODO set the doc on the variant instead of the enum if fields.len() == 1 { - let (_, type_mod_name, min_occurs, max_occurs, type_name) = fields.remove(0); + let (min_occurs, max_occurs, (type_mod_name, type_name)) = fields.remove(0); match (min_occurs, max_occurs) { (1, 1) => { variant.tuple(&format!("Box>", escape_keyword(&type_mod_name), escape_keyword(&type_name))); @@ -177,7 +180,13 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } else { impl_code.push(format!(" impl_struct_variant!({},", variant_name)); - for (field_name, type_mod_name, min_occurs, max_occurs, type_name) in fields { + let mut field_name_gen = NameGenerator::new(); + for (min_occurs, max_occurs, (type_mod_name, type_name)) in fields { + let field_name = NameHint::new(type_name); + let field_name = name_from_hint(&field_name).unwrap(); + let field_name = field_name.to_snake_case(); + let field_name = field_name_gen.gen_name(field_name); + let field_name = self.renames.get(&field_name).unwrap_or(&field_name); match (min_occurs, max_occurs) { (1, 1) => { impl_code.push(format!(" ({}, {}, Box<{}>),", field_name, type_mod_name, type_name)); @@ -199,20 +208,23 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } impl_code.push(");".to_string()); module.scope().raw(&impl_code.join("\n")); + Some(("choices".to_owned(), enum_name.to_owned())) } - fn gen_union(&self, items: &Vec, ()>>, doc: &Documentation<'input>) { - let items: Vec<_> = items.iter().filter_map(|item| self.gen_simple_type(item)).collect(); + fn gen_union(&self, items: &Vec>, doc: &Documentation<'input>) -> Option<(String, String)>{ + let items: Vec<_> = items.iter().filter_map( + |InlineSimpleType { type_ }| self.gen_simple_type(type_) + ).collect(); let mut name_hint = NameHint::new("union"); for item in items { - name_hint.extend(item.1); + name_hint.push(&item.1); } - let name = name_from_hint(name_hint); + let name = name_from_hint(&name_hint).unwrap(); let enum_name = escape_keyword(&name.to_camel_case()); let enum_name = self.name_gen.gen_name(enum_name); - let enum_name = self.renames.get(enum_name).unwrap_or(enum_name); + let enum_name = self.renames.get(&enum_name).unwrap_or(&enum_name); - let module = self.scope.module_get_mut("unions").unwrap(); + let module = self.scope.get_module_mut("unions").unwrap(); let mut impl_code = Vec::new(); impl_code.push(format!("impl_union!({}, {{", enum_name)); { @@ -222,7 +234,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } else if items.len() == 1 { // Shortcut if this is a union for a single type - return items.get(0) + return items.get(0).cloned() } else { let mut name_gen = NameGenerator::new(); @@ -235,19 +247,21 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } impl_code.push(format!("}});")); module.scope().raw(&impl_code.join("\n")); + Some(("union".to_owned(), enum_name.clone())) } fn gen_list(&self, item: &RichAstNode<'input, SimpleType<'input>, ()>, doc: &Documentation<'input>) -> Option<(String, String)> { if let Some((type_mod_name, type_name)) = self.gen_simple_type(item) { let mut name = NameHint::new("list"); - name.extend(type_name.to_camel_case()); + name.push(&type_name); + let name = name_from_hint(&name).unwrap().to_camel_case(); let name = escape_keyword(&name); let struct_name = self.name_gen.gen_name(name); let module = self.scope.get_module_mut("structs").unwrap(); let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); module.scope().raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); - Some(("lists", struct_name)) + Some(("lists".to_owned(), struct_name)) } else { None @@ -260,25 +274,20 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { // RichAstNode should be changed so impossibility is enforced by the type checker. panic!("Simple type with attributes???"); } - let (type_mod_name, type_name) = match type_ { + match type_ { SimpleType::Alias(name) => { - let (type_mod_name, local_names) = self.names.get(ty.namespace()) - .expect(&format!("Unknown namespace: {}", ty.namespace())); - let type_name = local_names.get(ty.local_name()) - .expect(&format!("Unknown type {} in namespace {}", ty.local_name(), ty.namespace())); - (type_mod_name, type_name) - }, - SimpleType::Restriction(name, facets) => self.gen_restriction(name, facets), - SimpleType::Union(items) => self.gen_union(items), - SimpleType::List(item) => self.gen_list(item), - SimpleType::Empty => { - return None + let (mod_name, ns_names) = self.names.get(&name.namespace()).expect("Unknown namespace"); + let type_name = ns_names.get(&name.local_name()).expect("Unknown simple type name"); + Some((mod_name.clone(), type_name.clone())) }, - }; - Some((type_mod_name, type_name)) + SimpleType::Restriction(name, facets) => self.gen_simple_restriction(*name, facets, doc), + SimpleType::Union(items) => self.gen_union(items, doc), + SimpleType::List(item) => self.gen_list(item, doc), + SimpleType::Empty => None, + } } - fn gen_simple_restriction(&mut self, base_name: FullName<'input>, facets: &Facets<'input>) { + fn gen_simple_restriction(&mut self, base_name: FullName<'input>, facets: &Facets<'input>, doc: &Documentation<'input>) -> Option<(String, String)> { let name = match &facets.enumeration { Some(items) => { if items.len() == 1 { @@ -321,6 +330,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { s.push(format!("assertion: {:?},", facets.assertion)); s.push(format!("explicit_timezone: {:?},", facets.explicit_timezone)); module.scope().raw(&format!("impl_simpletype_restriction!({}, Facets {{\n {}\n}});", name, s.join("\n "))); + Some(("enumeration".to_owned(), name)) } fn gen_fields(&self, empty_struct: &mut bool, struct_: &mut cg::Struct, impl_code: &mut Vec, doc: &mut Documentation<'input>, name_gen: &mut NameGenerator, type_: &Type<'input>) { @@ -354,19 +364,19 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &type_); } - fn gen_sequence(&mut self, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + fn gen_sequence(&mut self, items: &Vec>, doc: &Documentation<'input>)-> Option<(String, String)> { self.gen_group_or_sequence("sequence", NameHint::new("sequence"), items, doc) } - fn gen_group(&mut self, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + fn gen_group(&mut self, items: &Vec<&InlineComplexType<'input, ()>>, doc: &Documentation<'input>) -> Option<(String, String)> { self.gen_group_or_sequence("group", NameHint::new("group"), items, doc) } - fn gen_group_or_sequence(&mut self, mod_name: &str, name_hint: &NameHint<'input>, items: &Vec<&RichAstNode<'input, Type<'input>, ()>>, doc: &Documentation<'input>) { + fn gen_group_or_sequence(&mut self, mod_name: &str, name_hint: &NameHint<'input>, items: &Vec<&InlineComplexType<'input, ()>>, doc: &Documentation<'input>) -> Option<(String, String)> { let items: Vec<_> = items.iter().filter_map(|item| self.gen_simple_type(item)).collect(); for item in items { - name_hint.extend(item.1); + name_hint.push(&item.1); } - let struct_name = name_from_hint(name_hint); + let struct_name = name_from_hint(&name_hint); let struct_name = escape_keyword(&struct_name.to_camel_case()); let struct_name = self.name_gen.gen_name(struct_name); let struct_name = self.renames.get(&struct_name).unwrap_or(&struct_name); @@ -386,11 +396,13 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } struct_.doc(&doc.to_string()); if empty_struct { + // TODO: return None instead struct_.tuple_field(&format!("pub ::std::marker::PhantomData<&'input ()>")); } } impl_code.push(");".to_string()); module.scope().raw(&impl_code.join("\n")); + Some((mod_name.to_string(), struct_name)) } fn gen_inline_elements(&mut self) { diff --git a/xml-schema/src/processor.rs b/xml-schema/src/processor.rs index f163810..a1d21c9 100644 --- a/xml-schema/src/processor.rs +++ b/xml-schema/src/processor.rs @@ -144,7 +144,10 @@ pub enum Type<'input> { ElementRef(FullName<'input>), Element(FullName<'input>), Group(FullName<'input>), - Choice(Vec>), + Choice(Vec>>), + // ^- a field of a variant + // ^- a variant (anonymous struct) + // ^- list of variants Sequence(Vec>), Simple(SimpleType<'input>), } @@ -622,7 +625,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); let mut items = particles.iter().map(|particle| - self.process_nested_particle(particle, vec![]) + vec![self.process_nested_particle(particle, vec![])] ).collect(); let doc = self.process_annotation(&annotation.iter().collect()); InlineComplexType::new( From 1137c4848fdde4574cb31865939eb25c7ba03cb7 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sun, 7 Jul 2019 20:14:28 +0200 Subject: [PATCH 3/3] [WIP] progress --- xml-schema-tests/build.rs | 4 +- xml-schema/src/bin/gen.rs | 4 +- xml-schema/src/parser_generator.rs | 360 ++++++++++++++++------------- xml-schema/src/processor.rs | 66 +++--- 4 files changed, 234 insertions(+), 200 deletions(-) diff --git a/xml-schema-tests/build.rs b/xml-schema-tests/build.rs index 8cd63fa..079edfd 100644 --- a/xml-schema-tests/build.rs +++ b/xml-schema-tests/build.rs @@ -38,7 +38,7 @@ fn main() { let renames = Default::default(); let mut gen = ParserGenerator::new(vec![proc], &parse_context, renames); - let scope = gen.gen_target_scope(); + gen.gen_target_scope(); let filename = in_path.file_name().unwrap(); let out_path = @@ -53,7 +53,7 @@ fn main() { .write(b"#[allow(unused_imports)]\nuse xml_schema::support;\n") .expect(&format!("Could not write in {:?}", out_path)); out_file - .write(scope.to_string().as_bytes()) + .write(gen.scope.to_string().as_bytes()) .expect(&format!("Could not write in {:?}", out_path)); } println!("cargo:rerun-if-changed={}", in_dir.to_str().unwrap()); diff --git a/xml-schema/src/bin/gen.rs b/xml-schema/src/bin/gen.rs index 9e4fcfb..fb0696f 100644 --- a/xml-schema/src/bin/gen.rs +++ b/xml-schema/src/bin/gen.rs @@ -58,6 +58,6 @@ fn main() { } let mut gen = ParserGenerator::new(processors, &parse_context, renames); - let scope = gen.gen_target_scope(); - println!("#[allow(unused_imports)]\nuse support;\n{}", scope.to_string()); + gen.gen_target_scope(); + println!("#[allow(unused_imports)]\nuse support;\n{}", gen.scope.to_string()); } diff --git a/xml-schema/src/parser_generator.rs b/xml-schema/src/parser_generator.rs index 35bc300..58b63c3 100644 --- a/xml-schema/src/parser_generator.rs +++ b/xml-schema/src/parser_generator.rs @@ -39,7 +39,7 @@ pub struct ParserGenerator<'ast, 'input: 'ast> { renames: HashMap, name_gen: NameGenerator, - scope: cg::Scope, + pub scope: cg::Scope, self_gen: bool, } @@ -87,7 +87,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { self.scope.raw("pub use std::marker::PhantomData;"); self.create_modules(); self.gen_elements(); - self.gen_inline_elements(); + //self.gen_inline_elements(); } fn create_modules(&mut self) { @@ -119,6 +119,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { match type_ { Type::Choice(items) => self.gen_choice(items, doc), Type::Sequence(items) => self.gen_sequence(items, doc), + Type::Alias(name) => Some(self.get_type_name(*name)), _ => unimplemented!("{:?}", type_), } } @@ -131,8 +132,8 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { ).collect() ).collect(); let mut name_hint = NameHint::new("choice"); - for variant in items { - for (_min_occurs, _max_occurs, field) in variant { + for variant in items.iter() { + for (_min_occurs, _max_occurs, field) in variant.iter() { name_hint.push(&field.1); } } @@ -151,7 +152,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { for (i, fields) in items.iter().enumerate() { // TODO: handle min_occurs and max_occurs let mut doc = doc.clone(); - let variant_name = NameHint::new_empty(); + let mut variant_name = NameHint::new_empty(); for (_min_occurs, _max_occurs, (_mod_name, field_type_name)) in fields.iter() { variant_name.push(&field_type_name); } @@ -159,10 +160,10 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { let variant_name = escape_keyword(&variant_name.to_camel_case()); let variant_name = variant_name_gen.gen_name(variant_name); let variant_name = self.renames.get(&variant_name).unwrap_or(&variant_name); + // TODO set the doc on the variant instead of the enum let mut variant = enum_.new_variant(&variant_name); - enum_.doc(&doc.to_string()); // TODO set the doc on the variant instead of the enum if fields.len() == 1 { - let (min_occurs, max_occurs, (type_mod_name, type_name)) = fields.remove(0); + let (min_occurs, max_occurs, (type_mod_name, type_name)) = fields.get(0).unwrap(); match (min_occurs, max_occurs) { (1, 1) => { variant.tuple(&format!("Box>", escape_keyword(&type_mod_name), escape_keyword(&type_name))); @@ -181,7 +182,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { else { impl_code.push(format!(" impl_struct_variant!({},", variant_name)); let mut field_name_gen = NameGenerator::new(); - for (min_occurs, max_occurs, (type_mod_name, type_name)) in fields { + for (min_occurs, max_occurs, (type_mod_name, type_name)) in fields.iter() { let field_name = NameHint::new(type_name); let field_name = name_from_hint(&field_name).unwrap(); let field_name = field_name.to_snake_case(); @@ -210,13 +211,13 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { module.scope().raw(&impl_code.join("\n")); Some(("choices".to_owned(), enum_name.to_owned())) } - fn gen_union(&self, items: &Vec>, doc: &Documentation<'input>) -> Option<(String, String)>{ + fn gen_union(&mut self, items: &Vec>, doc: &Documentation<'input>) -> Option<(String, String)>{ let items: Vec<_> = items.iter().filter_map( |InlineSimpleType { type_ }| self.gen_simple_type(type_) ).collect(); let mut name_hint = NameHint::new("union"); - for item in items { + for item in items.iter() { name_hint.push(&item.1); } let name = name_from_hint(&name_hint).unwrap(); @@ -238,7 +239,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } else { let mut name_gen = NameGenerator::new(); - for (type_mod_name, type_name) in items { + for (type_mod_name, type_name) in items.iter() { let variant_name = name_gen.gen_name(type_name.to_camel_case()); enum_.new_variant(&variant_name).tuple(&format!("{}::{}<'input>", type_mod_name, type_name)); impl_code.push(format!(" impl_union_variant!({}),", variant_name)); @@ -250,16 +251,19 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { Some(("union".to_owned(), enum_name.clone())) } - fn gen_list(&self, item: &RichAstNode<'input, SimpleType<'input>, ()>, doc: &Documentation<'input>) -> Option<(String, String)> { - if let Some((type_mod_name, type_name)) = self.gen_simple_type(item) { + fn gen_list(&mut self, item: &InlineSimpleType<'input, ()>, doc: &Documentation<'input>) -> Option<(String, String)> { + let InlineSimpleType { type_ } = item; + if let Some((type_mod_name, type_name)) = self.gen_simple_type(type_) { let mut name = NameHint::new("list"); name.push(&type_name); let name = name_from_hint(&name).unwrap().to_camel_case(); let name = escape_keyword(&name); let struct_name = self.name_gen.gen_name(name); let module = self.scope.get_module_mut("structs").unwrap(); - let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let mut struct_ = cg::Struct::new(&struct_name); + struct_.vis("pub").derive("Debug").derive("PartialEq").generic("'input"); struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); + module.push_struct(struct_); module.scope().raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); Some(("lists".to_owned(), struct_name)) } @@ -268,18 +272,29 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_simple_type(&self, ty: &RichAstNode<'input, SimpleType<'input>, ()>) -> Option<(String, String)> { + fn get_type(&self, name: FullName<'input>) -> Option<&RichAstNode<'input, Type<'input>, ()>> { + for proc in self.processors.iter() { + if let Some(type_) = proc.complex_types.get(&name) { + return Some(type_) + } + } + None + } + + fn get_type_name(&self, name: FullName<'input>) -> (String, String) { + let (mod_name, ns_names) = self.names.get(&name.namespace()).expect("Unknown namespace"); + let type_name = ns_names.get(&name.local_name()).expect(&format!("Unknown simple type name {:?}", name)); + (mod_name.clone(), type_name.clone()) + } + + fn gen_simple_type(&mut self, ty: &RichAstNode<'input, SimpleType<'input>, ()>) -> Option<(String, String)> { let RichAstNode { attrs, type_, doc, data } = ty; if attrs.named.len() != 0 || attrs.refs.len() != 0 || attrs.group_refs.len() != 0 || attrs.any_attributes { // RichAstNode should be changed so impossibility is enforced by the type checker. panic!("Simple type with attributes???"); } match type_ { - SimpleType::Alias(name) => { - let (mod_name, ns_names) = self.names.get(&name.namespace()).expect("Unknown namespace"); - let type_name = ns_names.get(&name.local_name()).expect("Unknown simple type name"); - Some((mod_name.clone(), type_name.clone())) - }, + SimpleType::Alias(name) => Some(self.get_type_name(*name)), SimpleType::Restriction(name, facets) => self.gen_simple_restriction(*name, facets, doc), SimpleType::Union(items) => self.gen_union(items, doc), SimpleType::List(item) => self.gen_list(item, doc), @@ -301,9 +316,8 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { }; let name = name.to_camel_case(); let name = self.name_gen.gen_name(name.clone()); - self.simple_restrictions.insert((base_name.clone(), facets.clone()), name.clone()); - let (base_mod_name, base_type_name) = self.get_simple_type_name(&SimpleType::Alias(*base_name)).unwrap(); // TODO - let mut module = self.scope.get_module_mut("enumerations").unwrap(); + let (base_mod_name, base_type_name) = self.get_type_name(base_name); + let module = self.scope.get_module_mut("enumerations").unwrap(); module.scope().raw(&format!("#[derive(Debug, PartialEq)] pub struct {}<'input>(pub {}::{}<'input>);", name, base_mod_name, base_type_name)); let mut s = Vec::new(); let f = &mut |n: &Option<_>| { @@ -333,78 +347,81 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { Some(("enumeration".to_owned(), name)) } - fn gen_fields(&self, empty_struct: &mut bool, struct_: &mut cg::Struct, impl_code: &mut Vec, doc: &mut Documentation<'input>, name_gen: &mut NameGenerator, type_: &Type<'input>) { - let field_writer = &mut |name: String, type_mod_name: String, min_occurs, max_occurs, type_name: String| { - *empty_struct = false; - let name = escape_keyword(&name_gen.gen_name(name.to_snake_case())); - let name = self.renames.get(&name).unwrap_or(&name); - let type_mod_name = escape_keyword(&type_mod_name.to_snake_case()); - let type_name = escape_keyword(&type_name.to_camel_case()); - let type_name = self.renames.get(&type_name).unwrap_or(&type_name); - match (min_occurs, max_occurs) { - (1, 1) => { - struct_.field(&format!("pub {}", name), &format!("super::{}::{}<'input>", type_mod_name, type_name)); - impl_code.push(format!(" ({}, {}, {}),", name, type_mod_name, type_name)) - }, - (0, 1) => { - struct_.field(&format!("pub {}", name), &format!("Option>", type_mod_name, type_name)); - impl_code.push(format!(" ({}, {}, Option<{}>),", name, type_mod_name, type_name)) - }, - (_, ::std::usize::MAX) => { - struct_.field(&format!("pub {}", name), &format!("Vec>", type_mod_name, type_name)); - impl_code.push(format!(" ({}, {}, Vec<{}; min={};>),", name, type_mod_name, type_name, min_occurs)) - }, - (_, _) => { - struct_.field(&format!("pub {}", name), &format!("Vec>", type_mod_name, type_name)); - impl_code.push(format!(" ({}, {}, Vec<{}; min={}; max={};>),", name, type_mod_name, type_name, min_occurs, max_occurs)) - }, - } - }; - let doc_writer = &mut |doc2| doc.extend(doc2); - self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &type_); + fn gen_field(&self, empty_struct: &mut bool, struct_: &mut cg::Struct, impl_code: &mut Vec, doc: &Documentation<'input>, name_gen: &mut NameGenerator, min_occurs: usize, max_occurs: usize, type_name: (String, String)) { + let (type_mod_name, type_name) = type_name; + *empty_struct = false; + let name = escape_keyword(&name_gen.gen_name(type_name.to_snake_case())); + let name = self.renames.get(&name).unwrap_or(&name); + match (min_occurs, max_occurs) { + (1, 1) => { + struct_.field(&format!("pub {}", name), &format!("super::{}::{}<'input>", type_mod_name, type_name)); + impl_code.push(format!(" ({}, {}, {}),", name, type_mod_name, type_name)) + }, + (0, 1) => { + struct_.field(&format!("pub {}", name), &format!("Option>", type_mod_name, type_name)); + impl_code.push(format!(" ({}, {}, Option<{}>),", name, type_mod_name, type_name)) + }, + (_, ::std::usize::MAX) => { + struct_.field(&format!("pub {}", name), &format!("Vec>", type_mod_name, type_name)); + impl_code.push(format!(" ({}, {}, Vec<{}; min={};>),", name, type_mod_name, type_name, min_occurs)) + }, + (_, _) => { + struct_.field(&format!("pub {}", name), &format!("Vec>", type_mod_name, type_name)); + impl_code.push(format!(" ({}, {}, Vec<{}; min={}; max={};>),", name, type_mod_name, type_name, min_occurs, max_occurs)) + }, + } } fn gen_sequence(&mut self, items: &Vec>, doc: &Documentation<'input>)-> Option<(String, String)> { - self.gen_group_or_sequence("sequence", NameHint::new("sequence"), items, doc) + self.gen_group_or_sequence("sequence", "sequence", items, doc) } - fn gen_group(&mut self, items: &Vec<&InlineComplexType<'input, ()>>, doc: &Documentation<'input>) -> Option<(String, String)> { - self.gen_group_or_sequence("group", NameHint::new("group"), items, doc) + fn gen_group(&mut self, items: &Vec>, doc: &Documentation<'input>) -> Option<(String, String)> { + self.gen_group_or_sequence("group", "group", items, doc) } - fn gen_group_or_sequence(&mut self, mod_name: &str, name_hint: &NameHint<'input>, items: &Vec<&InlineComplexType<'input, ()>>, doc: &Documentation<'input>) -> Option<(String, String)> { - let items: Vec<_> = items.iter().filter_map(|item| self.gen_simple_type(item)).collect(); - - for item in items { - name_hint.push(&item.1); - } - let struct_name = name_from_hint(&name_hint); - let struct_name = escape_keyword(&struct_name.to_camel_case()); + fn gen_group_or_sequence(&mut self, mod_name: &str, name_prefix: &str, items: &Vec>, doc: &Documentation<'input>) -> Option<(String, String)> { + let items: Vec<_> = items.iter().filter_map( + |InlineComplexType { min_occurs, max_occurs, ref type_ }| + self.gen_complex_type(type_).map(|type_name| (*min_occurs, *max_occurs, type_name)) + ).collect(); + let struct_name = { + let mut name_hint = NameHint::new(name_prefix); + for (_min_occurs, _max_occurs, type_name) in items.iter() { + name_hint.push(&type_name.1); + } + let struct_name = name_from_hint(&name_hint).unwrap(); + let struct_name = escape_keyword(&struct_name.to_camel_case()); + struct_name + }; let struct_name = self.name_gen.gen_name(struct_name); let struct_name = self.renames.get(&struct_name).unwrap_or(&struct_name); - let mut module = self.scope.module_get_mut(mod_name).unwrap(); let mut impl_code = Vec::new(); impl_code.push(format!("impl_group_or_sequence!({},", struct_name)); + + let mut empty_struct = true; + let mut struct_ = cg::Struct::new(&struct_name); + struct_.vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let mut name_gen = NameGenerator::new(); + let mut doc = doc.clone(); { - let mut empty_struct = true; - let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - let mut name_gen = NameGenerator::new(); - let mut doc = doc.clone(); - { - for item in items { - self.gen_fields(&mut empty_struct, struct_, &mut impl_code, &mut doc, &mut name_gen, &item.type_); - } - } - struct_.doc(&doc.to_string()); - if empty_struct { - // TODO: return None instead - struct_.tuple_field(&format!("pub ::std::marker::PhantomData<&'input ()>")); + for (min_occurs, max_occurs, type_name) in items.into_iter() { + self.gen_field(&mut empty_struct, &mut struct_, &mut impl_code, &mut doc, &mut name_gen, min_occurs, max_occurs, type_name); } } + struct_.doc(&doc.to_string()); + if empty_struct { + // TODO: return None instead + struct_.tuple_field(&format!("pub ::std::marker::PhantomData<&'input ()>")); + } impl_code.push(");".to_string()); + + let module = self.scope.get_module_mut(mod_name).unwrap(); + module.push_struct(struct_); module.scope().raw(&impl_code.join("\n")); - Some((mod_name.to_string(), struct_name)) + Some((mod_name.to_owned(), struct_name.to_owned())) } + /* fn gen_inline_elements(&mut self) { let module = self.scope.new_module("inline_elements"); module.vis("pub"); @@ -428,44 +445,50 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { self.gen_element(module, &struct_names[0], &tag_name, attrs, element, doc); } } - } + }*/ fn gen_elements(&mut self) { - for proc in &self.processors { - let mut elements: Vec<_> = proc.elements.iter().collect(); - - elements.sort_by_key(|&(n,_)| n); - for (&name, element) in elements { - let mod_name = self.get_module_name(name); - let mut module = self.scope.get_module_mut(&mod_name).expect(&mod_name); - let head_local_name = format!("{}_head", name.local_name()); - let mut substitutions = Vec::new(); - substitutions.push(FullName::new(name.namespace(), &head_local_name)); - for proc in &self.processors { - if let Some(members) = proc.substitution_groups.get(&name) { - substitutions.extend(members); - } - } - if substitutions.len() > 1 { - let enum_name = escape_keyword(&name.local_name().to_camel_case()); - self.gen_substitution_enum(module.scope(), &enum_name, &substitutions); - let struct_name = escape_keyword(&head_local_name.to_camel_case()); - self.gen_element(module, &struct_name, &name, &element.attrs, &element.type_, &element.doc); - } - else { - let struct_name = escape_keyword(&name.local_name().to_camel_case()); - self.gen_element(module, &struct_name, &name, &element.attrs, &element.type_, &element.doc); - } + let elements: Vec<(FullName<'input>, InlineComplexType<'input, ()>)> = self.processors.iter().flat_map( + |proc| proc.elements.iter().map(|(name, type_)| (*name, type_.clone())) + ).collect(); + let mut elements = elements.clone(); // TODO: do not clone + + elements.sort_by_key(|&(n,_)| n); + + for (name, element) in elements { + self.gen_element_with_substitution(name, &element); + } + } + + fn gen_element_with_substitution(&mut self, name: FullName<'input>, element: &InlineComplexType<'input, ()>) { + let mut substitutions = Vec::new(); + substitutions.push(name); + for proc in self.processors.iter() { + if let Some(members) = proc.substitution_groups.get(&name) { + substitutions.extend(members); } } + + if substitutions.len() > 1 { + let enum_name = escape_keyword(&name.local_name().to_camel_case()); + self.gen_substitution_enum(&enum_name, &substitutions); + let head_local_name = format!("{}_head", name.local_name()); + let struct_name = escape_keyword(&head_local_name.to_camel_case()); + self.gen_element(&struct_name, name, element); + } + else { + let struct_name = escape_keyword(&name.local_name().to_camel_case()); + self.gen_element(&struct_name, name, element); + } } - fn gen_substitution_enum(&self, enum_name: &str, substitutions: &Vec>) { + fn gen_substitution_enum(&mut self, enum_name: &str, substitutions: &Vec>) { let mut impl_code = Vec::new(); impl_code.push(format!("impl_enum!({},", enum_name)); let mut name_gen = NameGenerator::new(); { - let enum_ = self.scope.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let mut enum_ = cg::Enum::new(&enum_name); + enum_.vis("pub").derive("Debug").derive("PartialEq").generic("'input"); for &substitution in substitutions { let variant_name = escape_keyword(&name_gen.gen_name(substitution.local_name().to_camel_case())); let type_mod_name = escape_keyword(&self.get_module_name(substitution).to_snake_case()); @@ -475,18 +498,19 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { impl_code.push(format!(" impl_singleton_variant!({}, {}, Box<{}>),", variant_name, escape_keyword(&type_mod_name), escape_keyword(&type_name))); } impl_code.push(");".to_string()); + self.scope.push_enum(enum_); } self.scope.raw(&impl_code.join("\n")); } - fn gen_attrs(&self, struct_: &mut cg::Struct, impl_code: &mut Vec, name_gen: &mut NameGenerator, attrs: &Attrs<'input>, seen_attrs: &mut HashMap, AttrUse>, generated_attrs: &mut HashSet>, inherited: bool) { + fn gen_attrs(&mut self, struct_: &mut cg::Struct, impl_code: &mut Vec, name_gen: &mut NameGenerator, attrs: &Attrs<'input>, seen_attrs: &mut HashMap, AttrUse>, generated_attrs: &mut HashSet>, inherited: bool) { for (attr_name, use_, attr_type) in &attrs.named { if generated_attrs.contains(attr_name) { continue; } - let default_type = SimpleType::Primitive(SCHEMA_URI, "AnySimpleType"); + let default_type = SimpleType::Alias(FullName::new(Some(SCHEMA_URI), "AnySimpleType")); let type_ = attr_type.as_ref().unwrap_or(&default_type); - let (type_mod_name, type_name) = self.get_simple_type_name(&type_).unwrap(); + let (type_mod_name, type_name) = self.gen_simple_type(&RichAstNode::new(type_.clone(), Documentation::new())).unwrap(); // FIXME: ugly let use_ = if inherited { *seen_attrs.get(attr_name).unwrap_or(use_) } @@ -510,72 +534,63 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } for group_name in &attrs.group_refs { - let mut found = false; + let mut found = None; for processor in self.processors.iter() { if let Some(attrs) = processor.attribute_groups.get(group_name) { - self.gen_attrs(struct_, impl_code, name_gen, attrs, seen_attrs, generated_attrs, false); - found = true; + found = Some(attrs.clone()); // TODO: do not clone break; } } - if !found { + if let Some(attrs) = found { + self.gen_attrs(struct_, impl_code, name_gen, &attrs, seen_attrs, generated_attrs, false); + } + else { panic!("unknown attribute group: {:?}", group_name); } } } - fn gen_element(&self, module: &mut cg::Module, struct_name: &str, tag_name: &FullName<'input>, attrs: &Attrs<'input>, type_: &Type<'input>, doc: &Documentation<'input>) { + fn gen_element(&mut self, struct_name: &str, tag_name: FullName<'input>, type_: &InlineComplexType<'input, ()>) { + let mod_name = self.get_module_name(tag_name); let mut impl_code = Vec::new(); impl_code.push(format!("impl_element!({}, {:?}, \"{}\", attributes = {{", struct_name, tag_name.namespace().unwrap_or(""), tag_name.local_name())); - { - let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - let mut empty_struct = false; - struct_.field("pub attrs", "HashMap, &'input str>"); - let mut name_gen = NameGenerator::new(); - let mut doc = doc.clone(); - let mut generated_attrs = HashSet::new(); - let mut seen_attrs = HashMap::new(); - - let attrs = self.compute_attrs(&type_, attrs); - self.gen_attrs(struct_, &mut impl_code, &mut name_gen, &attrs, &mut seen_attrs, &mut generated_attrs, false); - { - let field_writer = &mut |_, _, _, _, _| (); - let doc_writer = &mut |_| (); - self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &type_); - } - impl_code.push(format!("}}, fields = {{")); - self.gen_fields(&mut empty_struct, struct_, &mut impl_code, &mut doc, &mut name_gen, type_); - struct_.doc(&doc.to_string()); - } + let InlineComplexType { min_occurs, max_occurs, type_ } = type_; + + let mut struct_ = cg::Struct::new(&struct_name); + struct_.vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + let mut empty_struct = false; + struct_.field("pub attrs", "HashMap, &'input str>"); + let mut name_gen = NameGenerator::new(); + let mut generated_attrs = HashSet::new(); + let mut seen_attrs = HashMap::new(); + + println!("{:?}", type_); + let attrs = self.compute_attrs(&type_.type_, &type_.attrs); + self.gen_attrs(&mut struct_, &mut impl_code, &mut name_gen, &attrs, &mut seen_attrs, &mut generated_attrs, false); + /* WTF was this supposed to do? + * { + let field_writer = &mut |_, _, _, _, _| (); + let doc_writer = &mut |_| (); + self.write_type_in_struct_def(field_writer, &mut Some(doc_writer), &type_); + } */ + impl_code.push(format!("}}, fields = {{")); + if let Some((type_mod_name, type_name)) = self.gen_complex_type(type_) { + self.gen_field(&mut empty_struct, &mut struct_, &mut impl_code, &type_.doc, &mut name_gen, *min_occurs, *max_occurs, (type_mod_name, type_name)); + } + struct_.doc(&type_.doc.to_string()); + impl_code.push(format!("}});")); + let mut module = self.scope.get_module_mut(&mod_name).expect(&mod_name); + module.push_struct(struct_); module.scope().raw(&impl_code.join("\n")); } - fn get_type_generated_name(&self, name: &FullName<'input>) -> (&str, str) { - if name.namespace() == Some(SCHEMA_URI) { - if let Some(name) = self.primitive_types.get(name.local_name()) { - return name; - } - } - let mut type_ = None; - for proc in &self.processors { - if proc.target_namespace != name.namespace() { - continue; - } - type_ = proc.types.get(name); - if type_.is_some() { - break; - } - } - let type_ = type_.expect(&format!("Unknown type name: {:?}", name)); - type_ - } - + /* fn write_type_in_struct_def<'a, F, H>(&'a self, field_writer: &mut F, doc_writer: &mut Option<&mut H>, - type_: &'a Type<'input>, + type_: &'a InlineComplexType<'input, ()>, ) where F: FnMut(String, String, usize, usize, String), H: FnMut(&'a Documentation<'input>), @@ -632,34 +647,45 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } _ => unimplemented!("writing {:?}", type_), } - } + }*/ fn compute_attrs(&self, type_: &Type<'input>, own_attrs: &Attrs<'input>) -> Attrs<'input> { match type_ { Type::Alias(name) => { - let target_type = self.get_type(name); - let target_attrs = self.compute_attrs(&target_type.type_, &target_type.attrs); - self.extend_attrs(&target_attrs, own_attrs) + println!("{:?} {:?}", type_, name); + if let Some(target_type) = self.get_type(*name) { + let target_attrs = self.compute_attrs(&target_type.type_, &target_type.attrs); + self.extend_attrs(&target_attrs, own_attrs) + } + else { + // TODO: check that simple type exists + own_attrs.clone() + } }, - Type::InlineSequence(_) | - Type::Sequence(_, _, _) | - Type::Element(_, _, _) | - Type::Group(_, _, _) | - Type::ElementRef(_, _, _) | - Type::Choice(_, _, _) | + Type::Sequence(_) | + Type::Element(_) | + Type::Group(_) | + Type::ElementRef(_) | + Type::Choice(_) | Type::Empty | Type::Any => { own_attrs.clone() } Type::Extension(base, ext_type) => { - let base_type = &self.get_type(&base); + let base_type = &self.get_type(*base).unwrap(); let base_attrs = self.compute_attrs(&base_type.type_, &base_type.attrs); + let InlineComplexType { min_occurs, max_occurs, type_: ref ext_type } = **ext_type; + assert_eq!(min_occurs, 1); // FIXME: type of 'ext_type' + assert_eq!(max_occurs, 1); // FIXME: type of 'ext_type' let own_attrs = self.extend_attrs(own_attrs, &ext_type.attrs); // XXX self.extend_attrs(&base_attrs, &own_attrs) }, Type::Restriction(base, ext_type) => { - let base_type = &self.get_type(&base); + let base_type = &self.get_type(*base).unwrap(); let base_attrs = self.compute_attrs(&base_type.type_, &base_type.attrs); + let InlineComplexType { min_occurs, max_occurs, type_: ref ext_type } = **ext_type; + assert_eq!(min_occurs, 1); // FIXME: type of 'ext_type' + assert_eq!(max_occurs, 1); // FIXME: type of 'ext_type' let own_attrs = self.extend_attrs(own_attrs, &ext_type.attrs); // XXX self.restrict_attrs(&base_attrs, &own_attrs) }, diff --git a/xml-schema/src/processor.rs b/xml-schema/src/processor.rs index a1d21c9..eb16d6b 100644 --- a/xml-schema/src/processor.rs +++ b/xml-schema/src/processor.rs @@ -59,7 +59,7 @@ pub enum AttrUse { Optional, } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Attrs<'input> { pub named: Vec<(FullName<'input>, AttrUse, Option>)>, pub refs: Vec<(Option>, AttrUse, FullName<'input>)>, @@ -79,26 +79,25 @@ impl<'input> Attrs<'input> { } } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct RichAstNode<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct RichAstNode<'input, T: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { pub attrs: Attrs<'input>, pub type_: T, pub doc: Documentation<'input>, pub data: D, } -impl<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, T, D> { +impl<'input, T: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, T, D> { pub fn new(type_: T, doc: Documentation<'input>) -> RichAstNode<'input, T, D> { RichAstNode { attrs: Attrs::new(), type_, doc, data: D::default() } } } -impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, Type<'input>, D> { - fn add_attrs(mut self, new_attrs: Attrs<'input>) -> RichAstNode<'input, Type<'input>, D> { +impl<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, Type<'input>, D> { + fn add_attrs(&mut self, new_attrs: Attrs<'input>) { self.attrs.extend(new_attrs); - self } } -impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, SimpleType<'input>, D> { +impl<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> RichAstNode<'input, SimpleType<'input>, D> { pub fn into_complex(self) -> RichAstNode<'input, Type<'input>, D> { let RichAstNode { attrs, type_, doc, data } = self; RichAstNode { attrs, type_: Type::Simple(type_), doc, data } @@ -106,24 +105,24 @@ impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> Rich } /// A reference to a type, that can be part of another type/element/... -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct InlineComplexType<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { - min_occurs: usize, - max_occurs: usize, - type_: RichAstNode<'input, Type<'input>, D>, +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct InlineComplexType<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { + pub min_occurs: usize, + pub max_occurs: usize, + pub type_: RichAstNode<'input, Type<'input>, D>, } -impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineComplexType<'input, D> { +impl<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineComplexType<'input, D> { fn new(min_occurs: usize, max_occurs: usize, type_: RichAstNode<'input, Type<'input>, D>) -> InlineComplexType<'input, D> { InlineComplexType { min_occurs, max_occurs, type_ } } } /// A reference to a type, that can be part of another type/element/... -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct InlineSimpleType<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { - type_: RichAstNode<'input, SimpleType<'input>, D>, +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct InlineSimpleType<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> { + pub type_: RichAstNode<'input, SimpleType<'input>, D>, } -impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineSimpleType<'input, D> { +impl<'input, D: Debug + Clone + Hash + PartialEq + Eq + PartialOrd + Ord + Default> InlineSimpleType<'input, D> { fn new(type_: RichAstNode<'input, SimpleType<'input>, D>) -> InlineSimpleType<'input, D> { InlineSimpleType { type_ } } @@ -134,7 +133,7 @@ impl<'input, D: Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Default> Inli } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Type<'input> { Any, Empty, @@ -152,7 +151,7 @@ pub enum Type<'input> { Simple(SimpleType<'input>), } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum SimpleType<'input> { Alias(FullName<'input>), Restriction(FullName<'input>, Facets<'input>), @@ -167,7 +166,8 @@ pub struct Processor<'ast, 'input: 'ast> { pub element_form_default_qualified: bool, pub attribute_form_default_qualified: bool, pub elements: HashMap, InlineComplexType<'input, ()>>, - pub simple_types: HashMap, (InlineSimpleType<'input, ()>, Documentation<'input>)>, + pub simple_types: HashMap, (RichAstNode<'input, SimpleType<'input>, ()>, Documentation<'input>)>, + pub complex_types: HashMap, RichAstNode<'input, Type<'input>, ()>>, pub groups: HashMap, InlineComplexType<'input, ()>>, pub attribute_groups: HashMap, Attrs<'input>>, @@ -196,6 +196,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { groups: HashMap::new(), attribute_groups: HashMap::new(), simple_types: HashMap::new(), + complex_types: HashMap::new(), substitution_groups: HashMap::new(), _phantom: PhantomData::default(), } @@ -319,7 +320,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { }; let doc = self.process_annotation(&annotation); - self.simple_types.insert(name, (ty, doc.clone())); + self.simple_types.insert(name, (ty.type_, doc.clone())); InlineSimpleType::new( RichAstNode::new( SimpleType::Alias(name), @@ -392,16 +393,23 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { ) -> InlineComplexType<'input, ()> { let xs::ComplexType { ref attrs, ref attr_id, ref attr_name, ref attr_mixed, ref attr_abstract, ref attr_final, ref attr_block, ref attr_default_attributes_apply, ref annotation, ref complex_type_model } = complex_type; let name = attr_name; + let name = FullName::new(self.target_namespace, name.0); //let struct_name = self.namespaces.new_type(QName::from(name)); - let mut ty = match complex_type_model { + let ty = match complex_type_model { xs::ComplexTypeModel::SimpleContent(_) => unimplemented!("simpleContent"), xs::ComplexTypeModel::ComplexContent(ref model) => self.process_complex_content(model), xs::ComplexTypeModel::CompleteContentModel { ref open_content, ref type_def_particle, ref attr_decls, ref assertions } => self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions), }; - ty.type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); - ty + let InlineComplexType { min_occurs, max_occurs, mut type_ } = ty; + type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); + self.complex_types.insert(name, type_.clone()); + InlineComplexType::new( + min_occurs, max_occurs, + RichAstNode::new( + Type::Alias(name), + type_.doc.clone())) } fn process_local_complex_type(&mut self, @@ -428,7 +436,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_decls: &'ast xs::AttrDecls<'input>, assertions: &'ast xs::Assertions<'input>, ) -> InlineComplexType<'input, ()> { - let ty = match type_def_particle.as_ref() { + let mut ty = match type_def_particle.as_ref() { Some(type_def_particle) => self.process_type_def_particle(type_def_particle), None => InlineComplexType::new(1, 1, RichAstNode::new( Type::Empty, @@ -449,7 +457,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { ref sequence_open_content_type_def_particle, ref attr_decls, ref assertions } = **r; - let ty = match sequence_open_content_type_def_particle { + let mut ty = match sequence_open_content_type_def_particle { Some(sequences::SequenceOpenContentTypeDefParticle { open_content, type_def_particle }) => self.process_complex_restriction(attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref())), None => { @@ -469,7 +477,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { ref attrs, ref attr_base, ref attr_id, annotation: ref annotation2, ref open_content, ref type_def_particle, ref attr_decls, ref assertions } = **e; - let ty = match type_def_particle { + let mut ty = match type_def_particle { Some(type_def_particle) => self.process_extension(attrs, attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref())), None => self.process_trivial_extension(attrs, attr_base, vec_concat_opt(&annotation, annotation2.as_ref())), @@ -624,7 +632,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { let particles = nested_particle; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); - let mut items = particles.iter().map(|particle| + let items = particles.iter().map(|particle| vec![self.process_nested_particle(particle, vec![])] ).collect(); let doc = self.process_annotation(&annotation.iter().collect());