|
| 1 | +//! Collects named entities and global information from the root of the AST. |
| 2 | +use std::collections::hash_map::{Entry, HashMap}; |
| 3 | + |
| 4 | +use names::FullName; |
| 5 | +use parser::xs; |
| 6 | + |
| 7 | +fn insert_unique<'ast, 'input: 'ast, T>( |
| 8 | + type_name: &'static str, |
| 9 | + map: &mut HashMap<FullName<'input>, T>, |
| 10 | + name: FullName<'input>, |
| 11 | + sub_ast: T, |
| 12 | +) { |
| 13 | + let entry = map.entry(name); |
| 14 | + match entry { |
| 15 | + Entry::Occupied(_) => panic!("Duplicate {}: {:?}", type_name, name), |
| 16 | + Entry::Vacant(e) => { |
| 17 | + e.insert(sub_ast); |
| 18 | + } |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +#[derive(Debug)] |
| 23 | +pub struct Toplevel<'ast, 'input: 'ast> { |
| 24 | + pub target_namespace: Option<&'input str>, |
| 25 | + pub element_form_default_qualified: bool, |
| 26 | + pub attribute_form_default_qualified: bool, |
| 27 | + pub elements: HashMap<FullName<'input>, &'ast xs::Element<'input>>, |
| 28 | + pub simple_types: HashMap<FullName<'input>, &'ast xs::SimpleType<'input>>, |
| 29 | + pub complex_types: HashMap<FullName<'input>, &'ast xs::ComplexType<'input>>, |
| 30 | + pub groups: HashMap<FullName<'input>, &'ast xs::Group<'input>>, |
| 31 | + pub attribute_groups: HashMap<FullName<'input>, &'ast xs::AttributeGroup<'input>>, |
| 32 | +} |
| 33 | + |
| 34 | +impl<'ast, 'input: 'ast> Toplevel<'ast, 'input> { |
| 35 | + pub fn new(ast: &'ast xs::Schema<'input>) -> Toplevel<'ast, 'input> { |
| 36 | + let target_namespace = ast.attr_target_namespace.as_ref().map(|t| t.0); |
| 37 | + let element_form_default_qualified = |
| 38 | + match ast.attr_element_form_default.as_ref().map(|x| ((x.0).0).0) { |
| 39 | + Some("qualified") => true, |
| 40 | + Some("unqualified") | None => false, |
| 41 | + _ => unreachable!(), |
| 42 | + }; |
| 43 | + let attribute_form_default_qualified = match ast |
| 44 | + .attr_attribute_form_default |
| 45 | + .as_ref() |
| 46 | + .map(|x| ((x.0).0).0) |
| 47 | + { |
| 48 | + Some("qualified") => true, |
| 49 | + Some("unqualified") | None => false, |
| 50 | + _ => unreachable!(), |
| 51 | + }; |
| 52 | + let mut toplevel = Toplevel { |
| 53 | + target_namespace, |
| 54 | + element_form_default_qualified, |
| 55 | + attribute_form_default_qualified, |
| 56 | + elements: HashMap::new(), |
| 57 | + simple_types: HashMap::new(), |
| 58 | + complex_types: HashMap::new(), |
| 59 | + groups: HashMap::new(), |
| 60 | + attribute_groups: HashMap::new(), |
| 61 | + }; |
| 62 | + toplevel.process_ast(ast); |
| 63 | + toplevel |
| 64 | + } |
| 65 | + |
| 66 | + pub fn process_ast(&mut self, ast: &'ast xs::Schema<'input>) { |
| 67 | + for top_level_item in ast.sequence_schema_top_annotation.iter() { |
| 68 | + match top_level_item.schema_top { |
| 69 | + xs::SchemaTop::Redefinable(ref r) => self.process_redefinable(r), |
| 70 | + xs::SchemaTop::Element(ref e) => self.process_element(e), |
| 71 | + xs::SchemaTop::Attribute(_) => unimplemented!("top-level attribute"), |
| 72 | + xs::SchemaTop::Notation(_) => unimplemented!("notation"), |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + fn process_redefinable(&mut self, r: &'ast xs::Redefinable<'input>) { |
| 78 | + match r { |
| 79 | + xs::Redefinable::SimpleType(ref e) => self.process_simple_type(e), |
| 80 | + xs::Redefinable::ComplexType(e) => self.process_complex_type(e), |
| 81 | + xs::Redefinable::Group(e) => self.process_named_group(e), |
| 82 | + xs::Redefinable::AttributeGroup(e) => self.process_attribute_group(e), |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + fn process_element(&mut self, element: &'ast xs::Element<'input>) { |
| 87 | + let name = FullName::new(self.target_namespace, element.attr_name.0); |
| 88 | + insert_unique("element", &mut self.elements, name, element); |
| 89 | + } |
| 90 | + |
| 91 | + fn process_simple_type(&mut self, simple_type: &'ast xs::SimpleType<'input>) { |
| 92 | + let name = FullName::new(self.target_namespace, simple_type.attr_name.0.clone()); |
| 93 | + self.simple_types.insert(name, simple_type); |
| 94 | + } |
| 95 | + |
| 96 | + fn process_complex_type(&mut self, complex_type: &'ast xs::ComplexType<'input>) { |
| 97 | + let name = FullName::new(self.target_namespace, complex_type.attr_name.0.clone()); |
| 98 | + self.complex_types.insert(name, complex_type); |
| 99 | + } |
| 100 | + |
| 101 | + fn process_named_group(&mut self, group: &'ast xs::Group<'input>) { |
| 102 | + let name = FullName::new(self.target_namespace, group.attr_name.0.clone()); |
| 103 | + self.groups.insert(name, group); |
| 104 | + } |
| 105 | + |
| 106 | + fn process_attribute_group(&mut self, attribute_group: &'ast xs::AttributeGroup<'input>) { |
| 107 | + let name = FullName::new(self.target_namespace, attribute_group.attr_name.0.clone()); |
| 108 | + self.attribute_groups.insert(name, attribute_group); |
| 109 | + } |
| 110 | +} |
0 commit comments