pub fn parse_until<In: Input, Reason>(
pat: impl Pattern,
) -> impl Parser<In, In, Reason>Expand description
Parses a span of the input until a match of pattern pat is met.
The returned rest of the input will still have the match.
The returned parser never returns an error, if pred returns false for all the characters
in the input, then the output is the entire input, and the rest of the input is an empty string.
See also parse_while, parse_until_ex.
Examples found in repository?
examples/xml.rs (line 50)
49fn parse_ident<In: Input, Reason>(input: In) -> ParsingResult<In, In, Reason> {
50 parse_until(|c| ['>', '/', '='].contains(&c) || c.is_whitespace())
51 .filter(|i: &In| !i.is_empty())
52 .parse(input)
53}
54
55fn parse_string<In: Input>(input: In) -> ParsingResult<In, In, Error> {
56 parse('"')
57 .then(parse_until_ex(NotEscaped('\\', '"')).or_reason(Error::UnclosedString))
58 .parse(input)
59}
60
61fn parse_attr<In: Input>(input: In) -> ParsingResult<In, Attr<In>, Error> {
62 parse_ident
63 .skip(parse_whitespace)
64 .and(
65 parse('=')
66 .skip(parse_whitespace)
67 .then(parse_string.or_reason(Error::NoAttrValue))
68 .skip(parse_whitespace)
69 .maybe(),
70 )
71 .map_out(from_tuple!(Attr { name, value }))
72 .parse(input)
73}
74
75fn parse_tag<In: Input>(input: In) -> ParsingResult<In, Fragment<In>, Error> {
76 parse_whitespace::<In, Error>
77 .then(parse('<'))
78 .then(parse_whitespace)
79 .then(parse('/').ok())
80 .skip(parse_whitespace)
81 .and(parse_ident)
82 .skip(parse_whitespace)
83 .map(match_out! {
84 (true, name) => ready(Fragment::ClosingTag { name }),
85 (false, name) => parse_attr
86 .collect()
87 .and(parse('/').ok())
88 .skip(parse_whitespace)
89 .map_out(|(attrs, self_closing)| Fragment::Tag { self_closing, name: name.clone(), attrs })
90 })
91 .skip(parse_whitespace)
92 .skip(parse('>').or_reason(Error::TagUnclosed))
93 .parse(input)
94}
95
96fn xml_fragments<In: Input>(
97 input: In,
98) -> impl Iterator<Item = Result<Fragment<In>, ParsingError<In, Error>>> {
99 parse_tag
100 .or_nonempty(parse_until('<').map_out(Fragment::Text))
101 .iter(input)
102}