Skip to main content

relax_ng/
grammar.rs

1use std::collections::BTreeMap;
2
3/// A parsed (but not yet composed/simplified) RELAX NG schema, as returned
4/// by [`crate::parse`]. Pass it to [`crate::simplify`] (or use
5/// [`crate::Schema::compile`], which does both steps) to get a
6/// [`crate::CompiledSchema`] ready to validate documents against.
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct SchemaDocument {
9    pub(crate) root: Root,
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub(crate) enum Root {
14    Pattern(Pattern),
15    Grammar(Grammar),
16}
17
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub(crate) struct Grammar {
20    pub(crate) context: Context,
21    pub(crate) items: Vec<GrammarItem>,
22}
23
24#[derive(Clone, Debug, Eq, PartialEq)]
25pub(crate) enum GrammarItem {
26    Start {
27        combine: Option<Combine>,
28        body: Vec<Pattern>,
29    },
30    Define {
31        name: String,
32        combine: Option<Combine>,
33        body: Vec<Pattern>,
34    },
35    Div(Vec<GrammarItem>),
36    Include {
37        href: String,
38        inherit_namespace: Option<String>,
39        body: Vec<GrammarItem>,
40        context: Context,
41    },
42}
43
44#[derive(Clone, Copy, Debug, Eq, PartialEq)]
45pub(crate) enum Combine {
46    Choice,
47    Interleave,
48}
49
50#[derive(Clone, Debug, Eq, PartialEq)]
51pub(crate) enum Pattern {
52    Element {
53        name: NameClass,
54        body: Vec<Pattern>,
55        context: Context,
56    },
57    Attribute {
58        name: NameClass,
59        body: Vec<Pattern>,
60        context: Context,
61    },
62    Group(Vec<Pattern>),
63    Interleave(Vec<Pattern>),
64    Choice(Vec<Pattern>),
65    Optional(Vec<Pattern>),
66    ZeroOrMore(Vec<Pattern>),
67    OneOrMore(Vec<Pattern>),
68    List(Vec<Pattern>),
69    Mixed(Vec<Pattern>),
70    Empty,
71    NotAllowed,
72    Text,
73    Data {
74        datatype: String,
75        datatype_library: Option<String>,
76        params: Vec<Param>,
77        except: Vec<Pattern>,
78        context: Context,
79    },
80    Value {
81        value: String,
82        datatype: Option<String>,
83        datatype_library: Option<String>,
84        namespace: Option<String>,
85        context: Context,
86    },
87    Ref(String),
88    ParentRef(String),
89    ExternalRef {
90        href: String,
91        inherit_namespace: Option<String>,
92        context: Context,
93    },
94    Grammar(Grammar),
95}
96
97#[derive(Clone, Debug, Eq, PartialEq)]
98pub(crate) struct Param {
99    pub(crate) name: String,
100    pub(crate) value: String,
101    pub(crate) context: Context,
102}
103
104#[derive(Clone, Debug, Eq, PartialEq)]
105pub(crate) enum NameClass {
106    Name {
107        lexical: String,
108        namespace: Option<String>,
109        context: Context,
110    },
111    Any {
112        except: Vec<NameClass>,
113        context: Context,
114    },
115    Namespace {
116        namespace: Option<String>,
117        except: Vec<NameClass>,
118        context: Context,
119    },
120    Choice(Vec<NameClass>),
121}
122
123#[derive(Clone, Debug, Eq, PartialEq)]
124pub(crate) struct Context {
125    pub(crate) base_uri: String,
126    pub(crate) namespaces: BTreeMap<String, String>,
127    pub(crate) default_namespace: Option<String>,
128    /// §4.3: the nearest ancestor's `datatypeLibrary`, inherited down for
129    /// any `data`/`value` that doesn't specify its own.
130    pub(crate) datatype_library: Option<String>,
131    /// §4.9: the nearest ancestor's `ns`, inherited down for any `name`/
132    /// `nsName`/`value` that doesn't specify its own (`None` here means
133    /// "never set by any ancestor", which resolves to the empty string —
134    /// distinct from an ancestor explicitly setting `ns=""`, though both
135    /// end up meaning the same no-namespace default in practice).
136    pub(crate) ns: Option<String>,
137}