nom_xml/prolog/
declaration_content.rs1use crate::{namespaces::ParseNamespace, parse::Parse, ConditionalState, IResult, Name};
2use nom::{
3 branch::alt,
4 bytes::complete::tag,
5 combinator::{map, opt},
6 multi::many1,
7 sequence::{preceded, tuple},
8};
9
10use super::content_particle::ContentParticle;
11
12#[derive(Clone, PartialEq, Eq)]
13pub enum DeclarationContent {
14 Mixed(Mixed),
15 Children(ContentParticle),
16 Empty,
17 Any,
18}
19
20impl<'a> Parse<'a> for DeclarationContent {
21 type Args = ();
22 type Output = IResult<&'a str, Self>;
23 fn parse(input: &'a str, args: Self::Args) -> Self::Output {
25 alt((
26 map(tag("EMPTY"), |_| Self::Empty),
27 map(tag("ANY"), |_| Self::Any),
28 map(|i| Mixed::parse(i, args), Self::Mixed),
29 map(Self::parse_children, Self::Children),
30 ))(input)
31 }
32}
33impl<'a> ParseNamespace<'a> for DeclarationContent {}
34impl DeclarationContent {
35 fn parse_children(input: &str) -> IResult<&str, ContentParticle> {
37 let (input, particle) = alt((
38 map(
39 tuple((
40 ContentParticle::parse_choice,
41 opt(|i| ConditionalState::parse(i, ())),
42 )),
43 |(choice, state)| {
44 ContentParticle::Choice(choice, state.unwrap_or(ConditionalState::None))
45 },
46 ),
47 map(
48 tuple((
49 ContentParticle::parse_sequence,
50 opt(|i| ConditionalState::parse(i, ())),
51 )),
52 |(seq, state)| {
53 ContentParticle::Sequence(seq, state.unwrap_or(ConditionalState::None))
54 },
55 ),
56 ))(input)?;
57 Ok((input, particle))
58 }
59}
60
61#[derive(Clone, PartialEq, Eq)]
62pub enum Mixed {
63 PCDATA,
64 Names(Vec<Name>),
65}
66
67impl<'a> ParseNamespace<'a> for Mixed {}
68impl<'a> Parse<'a> for Mixed {
69 type Args = ();
70 type Output = IResult<&'a str, Self>;
71 fn parse(input: &'a str, _args: Self::Args) -> Self::Output {
75 alt((
76 map(
77 tuple((
78 tag("("),
79 Self::parse_multispace0,
80 tag("#PCDATA"),
81 many1(preceded(
82 tuple((Self::parse_multispace0, tag("|"), Self::parse_multispace0)),
83 alt((Self::parse_name, Self::parse_qualified_name)),
84 )),
85 Self::parse_multispace0,
86 tag(")*"),
87 )),
88 |(_, _, _, names, _, _)| Mixed::Names(names),
89 ),
90 map(
91 tuple((
92 tag("("),
93 Self::parse_multispace0,
94 tag("#PCDATA"),
95 Self::parse_multispace0,
96 tag(")"),
97 )),
98 |_| Mixed::PCDATA,
99 ),
100 ))(input)
101 }
102}