Skip to main content

ooxml_codegen/
ast.rs

1//! AST types for RELAX NG Compact syntax (subset used by OOXML schemas).
2
3/// A complete RNC schema file.
4#[derive(Debug, Clone)]
5pub struct Schema {
6    pub namespaces: Vec<Namespace>,
7    pub definitions: Vec<Definition>,
8}
9
10/// Namespace declaration: `namespace prefix = "uri"` or `default namespace prefix = "uri"`.
11#[derive(Debug, Clone)]
12pub struct Namespace {
13    pub prefix: String,
14    pub uri: String,
15    pub is_default: bool,
16}
17
18/// A named definition: `name = pattern`.
19#[derive(Debug, Clone)]
20pub struct Definition {
21    pub name: String,
22    pub pattern: Pattern,
23    pub doc_comment: Option<String>,
24}
25
26/// RELAX NG pattern (simplified for OOXML schemas).
27#[derive(Debug, Clone)]
28pub enum Pattern {
29    /// Empty content.
30    Empty,
31    /// Reference to another definition.
32    Ref(String),
33    /// `element name { pattern }`.
34    Element { name: QName, pattern: Box<Pattern> },
35    /// `attribute name { pattern }`.
36    Attribute { name: QName, pattern: Box<Pattern> },
37    /// Sequence: `pattern, pattern`.
38    Sequence(Vec<Pattern>),
39    /// Choice: `pattern | pattern`.
40    Choice(Vec<Pattern>),
41    /// Interleave (unordered): `pattern & pattern`.
42    Interleave(Vec<Pattern>),
43    /// Optional: `pattern?`.
44    Optional(Box<Pattern>),
45    /// Zero or more: `pattern*`.
46    ZeroOrMore(Box<Pattern>),
47    /// One or more: `pattern+`.
48    OneOrMore(Box<Pattern>),
49    /// String literal: `string "value"`.
50    StringLiteral(String),
51    /// XSD datatype: `xsd:integer`, `xsd:string`, etc.
52    Datatype {
53        library: String,
54        name: String,
55        params: Vec<DatatypeParam>,
56    },
57    /// Parenthesized pattern.
58    Group(Box<Pattern>),
59    /// Mixed content: `mixed { pattern }`.
60    Mixed(Box<Pattern>),
61    /// List content: `list { pattern }` (space-separated).
62    List(Box<Pattern>),
63    /// Text content.
64    Text,
65    /// Any content (wildcard pattern).
66    Any,
67}
68
69/// Qualified name with optional prefix.
70#[derive(Debug, Clone)]
71pub struct QName {
72    pub prefix: Option<String>,
73    pub local: String,
74}
75
76/// Name class for element/attribute names (supports wildcards and exclusions).
77#[derive(Debug, Clone)]
78pub enum NameClass {
79    /// A specific qualified name.
80    Name(QName),
81    /// Wildcard: `*` (any name).
82    AnyName,
83    /// Namespace wildcard: `ns:*` (any name in namespace).
84    NsName(String),
85    /// Choice of name classes: `nc1 | nc2`.
86    Choice(Vec<NameClass>),
87    /// Subtraction: `nc1 - nc2` (nc1 except nc2).
88    Except(Box<NameClass>, Box<NameClass>),
89}
90
91/// Datatype parameter: `{ length = "4" }`.
92#[derive(Debug, Clone)]
93pub struct DatatypeParam {
94    pub name: String,
95    pub value: String,
96}
97
98impl Pattern {
99    /// Returns true if this pattern represents a simple type (enum of string literals).
100    pub fn is_simple_type(&self) -> bool {
101        match self {
102            Pattern::Choice(variants) => variants
103                .iter()
104                .all(|v| matches!(v, Pattern::StringLiteral(_))),
105            Pattern::StringLiteral(_) => true,
106            Pattern::Datatype { .. } => true,
107            _ => false,
108        }
109    }
110}