ftml/parsing/collect/text.rs
1/*
2 * parsing/collect/text.rs
3 *
4 * ftml - Library to parse Wikidot text
5 * Copyright (C) 2019-2025 Wikijump Team
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21use super::prelude::*;
22
23/// Generic function to consume all tokens into a single string slice.
24///
25/// This is a subset of the functionality provided by `collect()`,
26/// as it specifically gathers all the extracted tokens into a string slice,
27/// rather than considering them as special elements.
28#[inline]
29pub fn collect_text<'p, 'r, 't>(
30 parser: &'p mut Parser<'r, 't>,
31 rule: Rule,
32 close_conditions: &[ParseCondition],
33 invalid_conditions: &[ParseCondition],
34 error_kind: Option<ParseErrorKind>,
35) -> Result<&'t str, ParseError>
36where
37 'r: 't,
38{
39 collect_text_keep(
40 parser,
41 rule,
42 close_conditions,
43 invalid_conditions,
44 error_kind,
45 )
46 .map(|(slice, _)| slice)
47}
48
49/// Modified form of `collect_text()` that also returns the last token.
50///
51/// The last token terminating the collection is kept, and returned
52/// to the caller alongside the string slice.
53///
54/// Compare with `collect_consume_keep()`.
55pub fn collect_text_keep<'p, 'r, 't>(
56 parser: &'p mut Parser<'r, 't>,
57 rule: Rule,
58 close_conditions: &[ParseCondition],
59 invalid_conditions: &[ParseCondition],
60 error_kind: Option<ParseErrorKind>,
61) -> Result<(&'t str, &'r ExtractedToken<'t>), ParseError>
62where
63 'r: 't,
64{
65 // Log collect_text() call
66 debug!("Trying to consume tokens to merge into a single string");
67
68 let (start, mut end) = (parser.current(), None);
69
70 // Iterate and collect the tokens to merge.
71 //
72 // We know text is always paragraph safe, so we ignore that value.
73 let (last, errors, _) = collect(
74 parser,
75 rule,
76 close_conditions,
77 invalid_conditions,
78 error_kind,
79 |parser| {
80 trace!("Ingesting token in string span");
81
82 end = Some(parser.current());
83 ok!(true; ())
84 },
85 )?
86 .into();
87
88 assert!(
89 errors.is_empty(),
90 "Exceptions were returned during text token collection",
91 );
92
93 let slice = match (start, end) {
94 // We have a token span, use to get string slice
95 (start, Some(end)) => parser.full_text().slice(start, end),
96
97 // Empty list of tokens, resultant slice must be empty
98 (_, None) => "",
99 };
100
101 Ok((slice, last))
102}