1use crate::{namespaces::ParseNamespace, parse::Parse, ConditionalState, IResult, Name};
2use nom::{
3 branch::alt,
4 character::complete::char,
5 combinator::{map, opt},
6 multi::{many0, many1},
7 sequence::{delimited, tuple},
8};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub enum ContentParticle {
12 Name(Name, ConditionalState),
13 Choice(Vec<ContentParticle>, ConditionalState),
14 Sequence(Vec<ContentParticle>, ConditionalState),
15}
16impl<'a> ParseNamespace<'a> for ContentParticle {}
17impl<'a> Parse<'a> for ContentParticle {
18 type Args = ();
19 type Output = IResult<&'a str, Self>;
20
21 fn parse(input: &'a str, _args: Self::Args) -> Self::Output {
24 let (input, res) = alt((
25 map(
26 tuple((
27 alt((Self::parse_name, Self::parse_qualified_name)),
28 opt(|i| ConditionalState::parse(i, ())),
29 )),
30 |(name, conditional_state)| {
31 ContentParticle::Name(name, conditional_state.unwrap_or(ConditionalState::None))
32 },
33 ),
34 map(
35 tuple((Self::parse_choice, opt(|i| ConditionalState::parse(i, ())))),
36 |(choice, conditional_state)| {
37 ContentParticle::Choice(
38 choice,
39 conditional_state.unwrap_or(ConditionalState::None),
40 )
41 },
42 ),
43 map(
44 tuple((
45 Self::parse_sequence,
46 opt(|i| ConditionalState::parse(i, ())),
47 )),
48 |(sequence, conditional_state)| {
49 ContentParticle::Sequence(
50 sequence,
51 conditional_state.unwrap_or(ConditionalState::None),
52 )
53 },
54 ),
55 ))(input)?;
56 Ok((input, res))
57 }
58}
59
60impl ContentParticle {
61 pub fn parse_choice(input: &str) -> IResult<&str, Vec<ContentParticle>> {
63 map(
64 delimited(
65 tuple((char('('), Self::parse_multispace0)),
66 tuple((
67 |i| Self::parse(i, ()),
68 many1(tuple((
69 tuple((Self::parse_multispace0, char('|'), Self::parse_multispace0)),
70 |i| Self::parse(i, ()),
71 ))),
72 )),
73 tuple((Self::parse_multispace0, char(')'))),
74 ),
75 |(first_cp, others)| {
76 let mut all_cps = Vec::new();
77 all_cps.push(first_cp);
78 all_cps.extend(others.into_iter().map(|(_, cp)| cp));
79 all_cps
80 },
81 )(input)
82 }
83
84 pub fn parse_sequence(input: &str) -> IResult<&str, Vec<ContentParticle>> {
86 map(
87 delimited(
88 tuple((char('('), Self::parse_multispace0)),
89 tuple((
90 |i| Self::parse(i, ()),
91 many0(tuple((
92 tuple((Self::parse_multispace0, char(','), Self::parse_multispace0)),
93 |i| Self::parse(i, ()),
94 ))),
95 )),
96 tuple((Self::parse_multispace0, char(')'))),
97 ),
98 |(first_cp, others)| {
99 let mut all_cps = Vec::new();
100 all_cps.push(first_cp);
101 all_cps.extend(others.into_iter().map(|(_, cp)| cp));
102 all_cps
103 },
104 )(input)
105 }
106}