Skip to content

Commit bae923f

Browse files
committed
Add lift_attrs.rs.
1 parent 9bce1f4 commit bae923f

File tree

8 files changed

+281
-77
lines changed

8 files changed

+281
-77
lines changed

xml-schema/src/asts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub mod non_recursive {
2828
Extra(TExtra),
2929
}
3030

31-
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
31+
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
3232
pub enum SimpleType<'input> {
3333
Alias(ConcreteName),
3434
Restriction(ConcreteName, Facets<'input>),
@@ -64,7 +64,7 @@ pub mod recursive {
6464
Simple(SimpleType<'input>),
6565
}
6666

67-
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
67+
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
6868
pub enum SimpleType<'input> {
6969
Primitive(&'static str, &'static str),
7070
Alias(FullName<'input>),

xml-schema/src/attrs.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
2+
pub enum AttrUse {
3+
Prohibited,
4+
Required,
5+
Optional,
6+
}
7+
8+
pub mod with_refs {
9+
use names::FullName;
10+
11+
use super::AttrUse;
12+
13+
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
14+
pub struct Attrs<'input, TSimpleType: Clone> {
15+
pub named: Vec<(FullName<'input>, AttrUse, Option<TSimpleType>)>,
16+
pub refs: Vec<(Option<FullName<'input>>, AttrUse, FullName<'input>)>,
17+
pub group_refs: Vec<FullName<'input>>,
18+
pub any_attributes: bool,
19+
}
20+
21+
impl<'input, TSimpleType> Attrs<'input, TSimpleType> where TSimpleType: Clone {
22+
pub fn new() -> Attrs<'input, TSimpleType> {
23+
Attrs {
24+
named: Vec::new(),
25+
refs: Vec::new(),
26+
group_refs: Vec::new(),
27+
any_attributes: false,
28+
}
29+
}
30+
31+
pub fn extend(&mut self, other: Attrs<'input, TSimpleType>) {
32+
let Attrs {
33+
named,
34+
refs,
35+
group_refs,
36+
any_attributes,
37+
} = other;
38+
self.named.extend(named);
39+
self.refs.extend(refs);
40+
self.group_refs.extend(group_refs);
41+
self.any_attributes |= any_attributes;
42+
}
43+
}
44+
}

xml-schema/src/attrs_bubble_up.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

xml-schema/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ pub mod bigfloat;
1616
pub mod utils;
1717

1818
pub mod asts;
19+
pub mod attrs;
1920
pub mod toplevel;
2021
pub mod processor2;
21-
pub mod attrs_bubble_up;
22+
pub mod lift_attrs;
2223
pub mod name_allocator;
23-
pub mod ungroup;
24+
//pub mod ungroup;
2425
//pub mod parser_generator2;
2526

2627
pub mod parser;

xml-schema/src/lift_attrs.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
//! Pushes attr definitions from the inner types of an element to the
2+
//! top-level element
3+
//!
4+
//! This module must compute a transitive closure in case of circular
5+
//! references:
6+
//! "Circular reference is not disallowed. [...] The effect is to take the
7+
//! transitive closure of the reference relation"
8+
//! https://www.w3.org/TR/xmlschema11-1/#declare-attributeGroup-core
9+
10+
use std::collections::{HashMap, HashSet};
11+
12+
use asts;
13+
use asts::recursive::ComplexType as RComplexType;
14+
use names::FullName;
15+
use utils::Bottom;
16+
17+
use processor2::ComplexTypeExtra as InComplexTypeExtra;
18+
use processor2::OutAttrs as InAttrs;
19+
use processor2::OutComplexType as InComplexType;
20+
use processor2::OutSimpleType as InSimpleType;
21+
22+
pub type OutSimpleType<'input> = InSimpleType<'input>;
23+
pub type OutComplexType<'input> = asts::recursive::ComplexType<'input, OutAttrs<'input>, Bottom>;
24+
pub type OutAttrs<'input> = InAttrs<'input>;
25+
26+
pub struct AttrsLifter<'input> {
27+
/// For each type name, stores a list of types that reference it.
28+
/// So if the former's list of attrs is updated, then the latter's
29+
/// must be updated as well.
30+
reverse_deps: HashMap<FullName<'input>, HashSet<FullName<'input>>>,
31+
32+
/// (A subset of) the attrs of each complex type. Can converge to the full
33+
/// attrs by calling `make_transitive_closure()`
34+
attrs_of_complex_type: HashMap<FullName<'input>, OutAttrs<'input>>,
35+
36+
/// Set of elements of `attrs_of_complex_type` that are strict subset of
37+
/// what they should be, and therefore should be updated.
38+
outdated_complex_types: HashSet<FullName<'input>>,
39+
40+
complex_types: HashMap<FullName<'input>, InComplexType<'input>>,
41+
}
42+
43+
impl<'input> AttrsLifter<'input> {
44+
pub fn with_capacity(capacity: usize) -> AttrsLifter<'input> {
45+
AttrsLifter {
46+
reverse_deps: HashMap::with_capacity(capacity),
47+
attrs_of_complex_type: HashMap::with_capacity(capacity),
48+
outdated_complex_types: HashSet::with_capacity(capacity),
49+
complex_types: HashMap::with_capacity(capacity),
50+
}
51+
}
52+
53+
pub fn add_complex_type(
54+
&mut self,
55+
name: FullName<'input>,
56+
complex_type: InComplexType<'input>,
57+
) {
58+
self.add_reverse_deps(name, &complex_type);
59+
self.complex_types.insert(name, complex_type);
60+
self.outdated_complex_types.insert(name);
61+
}
62+
63+
pub fn make_transitive_closure(&mut self) {
64+
while let Some(&name) = self.outdated_complex_types.iter().next() {
65+
let complex_type = self.complex_types.get(&name).expect("Name {} was supposed to be updated, but it missing from AttrsLifter.complex_types.");
66+
let attrs = self.get_attrs_step(complex_type);
67+
if self.attrs_of_complex_type.get(&name) != attrs.as_ref() {
68+
self.outdated_complex_types.insert(name);
69+
let attrs = attrs.expect(
70+
"attrs were Some() but became None while computing transitive closure.",
71+
);
72+
self.attrs_of_complex_type.insert(name, attrs);
73+
}
74+
}
75+
}
76+
77+
fn add_reverse_deps(
78+
&mut self,
79+
my_name: FullName<'input>,
80+
complex_type: &InComplexType<'input>,
81+
) {
82+
let add_rev_dep = &mut |rev_dep| {
83+
self.reverse_deps
84+
.get_mut(rev_dep)
85+
.expect(&format!("Reverse deps map is missing {:?} entry", rev_dep))
86+
.insert(my_name);
87+
};
88+
89+
match complex_type {
90+
// Trivial cases
91+
RComplexType::Any => {}
92+
RComplexType::Empty => {}
93+
RComplexType::Alias(fullname) => add_rev_dep(fullname),
94+
// The actual work
95+
RComplexType::Extension(base, inner) | RComplexType::Restriction(base, inner) => {
96+
add_rev_dep(base);
97+
self.add_reverse_deps(my_name, inner);
98+
}
99+
RComplexType::ElementRef(_min_occurs, _max_occurs, fullname) => add_rev_dep(fullname),
100+
RComplexType::Choice(_min_occurs, _max_occurs, inners)
101+
| RComplexType::Sequence(_min_occurs, _max_occurs, inners) => {
102+
for inner in inners {
103+
self.add_reverse_deps(my_name, inner);
104+
}
105+
}
106+
RComplexType::Simple(_simple_type) => {}
107+
108+
RComplexType::Element(_min_occurs, _max_occurs, _fullname, _attrs, inner) => {
109+
self.add_reverse_deps(my_name, inner);
110+
}
111+
RComplexType::GroupRef(_min_occurs, _max_occurs, _fullname) => unimplemented!(),
112+
RComplexType::Extra(InComplexTypeExtra::AttrDecl(_attrs, inner)) => {
113+
self.add_reverse_deps(my_name, inner);
114+
}
115+
}
116+
}
117+
118+
fn get_attrs_step(&self, complex_type: &InComplexType<'input>) -> Option<OutAttrs<'input>> {
119+
let merge_attrs = |attrs1: Option<&OutAttrs<'input>>, attrs2| match (attrs1, attrs2) {
120+
(None, attrs2) => attrs2,
121+
(Some(attrs1), None) => Some(attrs1.clone()),
122+
(Some(attrs1), Some(attrs2)) => {
123+
let mut attrs: OutAttrs<'input> = attrs1.clone();
124+
attrs.extend(attrs2);
125+
Some(attrs)
126+
}
127+
};
128+
match complex_type {
129+
RComplexType::Any => None,
130+
RComplexType::Empty => None,
131+
RComplexType::Alias(fullname) => self.attrs_of_complex_type.get(fullname).cloned(),
132+
133+
RComplexType::Extension(base, inner) => merge_attrs(
134+
self.attrs_of_complex_type.get(base),
135+
self.get_attrs_step(inner),
136+
),
137+
RComplexType::Restriction(base, inner) => {
138+
// Attributes are inherited from the base:
139+
// "However, attribute declarations do not need to be repeated in the derived type definition"
140+
// https://www.w3.org/TR/xmlschema-0/#DerivByRestrict
141+
merge_attrs(
142+
self.attrs_of_complex_type.get(base),
143+
self.get_attrs_step(inner),
144+
)
145+
}
146+
RComplexType::ElementRef(_min_occurs, _max_occurs, _fullname) => None,
147+
148+
RComplexType::Choice(_min_occurs, _max_occurs, inners)
149+
| RComplexType::Sequence(_min_occurs, _max_occurs, inners) => {
150+
for inner in inners {
151+
if self.get_attrs_step(inner).is_some() {
152+
unimplemented!(
153+
"Sequence/choice got attribute declaration. \
154+
I don't know what to do with that."
155+
);
156+
}
157+
}
158+
None
159+
}
160+
RComplexType::Simple(_simple_type) => None,
161+
162+
RComplexType::Element(_min_occurs, _max_occurs, _fullname, _attrs, _inner) => {
163+
// Elements capture the attrs for themselves and don't pass any up
164+
None
165+
}
166+
RComplexType::GroupRef(_min_occurs, _max_occurs, fullname) => {
167+
self.attrs_of_complex_type.get(fullname).cloned()
168+
}
169+
RComplexType::Extra(InComplexTypeExtra::AttrDecl(attrs, inner)) => {
170+
match self.get_attrs_step(inner) {
171+
Some(inner_attrs) => {
172+
let mut attrs = attrs.clone();
173+
attrs.extend(inner_attrs);
174+
Some(attrs)
175+
}
176+
None => Some(attrs.clone()),
177+
}
178+
}
179+
}
180+
}
181+
}

xml-schema/src/name_allocator.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@ use std::collections::hash_map::Entry;
44
use std::collections::HashMap;
55

66
use asts;
7-
use attrs_bubble_up::Attrs;
7+
use attrs::with_refs::Attrs;
88
use names::{name_from_hint, FullName, NameGenerator, NameHint};
9-
use utils::Bottom;
109

1110
use asts::non_recursive::ComplexType as NRComplexType;
1211
use asts::non_recursive::ConcreteName;
1312
use asts::non_recursive::SimpleType as NRSimpleType;
1413
use asts::recursive::ComplexType as RComplexType;
1514
use asts::recursive::SimpleType as RSimpleType;
1615

17-
use attrs_bubble_up::OutSimpleType as InSimpleType;
18-
use attrs_bubble_up::OutComplexType as InComplexType;
16+
use lift_attrs::OutAttrs as InAttrs;
17+
use lift_attrs::OutComplexType as InComplexType;
18+
use lift_attrs::OutSimpleType as InSimpleType;
1919

2020
pub type OutSimpleType<'input> = asts::non_recursive::SimpleType<'input>;
2121
pub type OutComplexType<'input> =
22-
asts::non_recursive::ComplexType<'input, Attrs<'input, ConcreteName>, ComplexTypeExtra<'input>>;
22+
asts::non_recursive::ComplexType<'input, OutAttrs<'input>, ComplexTypeExtra<'input>>;
23+
pub type OutAttrs<'input> = Attrs<'input, ConcreteName>;
2324

2425
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
2526
pub enum ComplexTypeExtra<'input> {
@@ -260,8 +261,8 @@ impl<'input> NameAllocator<'input> {
260261
fn allocate_attrs(
261262
&mut self,
262263
_namespace: Option<&'input str>,
263-
_attrs: &Attrs<'input, InSimpleType>,
264-
) -> Attrs<'input, ConcreteName> {
264+
_attrs: &InAttrs<'input>,
265+
) -> OutAttrs<'input> {
265266
unimplemented!()
266267
}
267268
}

0 commit comments

Comments
 (0)