MySQL 9.6.0
Source Code Documentation
fluent_parser.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_STRCONV_DECODE_FLUENT_PARSER_H
25#define MYSQL_STRCONV_DECODE_FLUENT_PARSER_H
26
27/// @file
28/// Experimental API header
29
30#include <concepts> // invocable
31#include <cstddef> // ptrdiff_t
32#include <utility> // forward
33#include "mysql/strconv/decode/parser.h" // Parser
34#include "mysql/strconv/decode/repeat.h" // Repeat
35#include "mysql/utils/return_status.h" // Return_status
36
37/// @addtogroup GroupLibsMysqlStrconv
38/// @{
39
40namespace mysql::strconv {
41
42// NOLINTBEGIN(performance-enum-size): silence clang-tidy's pointless hint
43
44/// Used in read_repeated_with_separators: if `yes,` the separator may be
45/// repeated more than once whenever it occurs.
47/// Used in read_repeated_with_separators: if `yes`, the string must start with
48/// a separator; if `no`, the string must not start with a separator; if
49/// `optional`, the string may or may not start with a separator.
51/// Used in read_repeated_with_separators: if `yes`, the string must end with a
52/// separator; if `no`, the string must not end with a separator; if `optional`,
53/// the string may or may not end with a separator.
55
56// NOLINTEND(performance-enum-size)
57
58/// Fluent API for parsing strings.
59///
60/// This provides a higher-level, fluent API that wraps a lower-level
61/// Parser. An instance represents the parser together with the state of
62/// the fluent API.
63///
64/// By using the fluent API, parsers that read multiple sub-objects in sequence
65/// can often be implemented without having to explicitly handle the failure of
66/// each sub-object parser. This can make the implementation safer and the code
67/// clearer.
68///
69/// In general, the state of the Fluent_parser is either "open" or "closed".
70/// The state determines whether subsequent invocations of member functions are
71/// inhibited or not: when in "open" state, subsequent invocations are
72/// executed, and when in "closed" state, subsequent invocations do nothing. If
73/// the state is "open" and the user invokes a member function, the state
74/// remains "open" if the function succeeds and changes to "closed" if the
75/// function fails. This enables patterns such as the following for parsing a
76/// sequence of tokens:
77///
78/// @code
79/// fluent_parser
80/// .read(object1)
81/// .read(object2)
82/// .read(object3);
83/// @endcode
84///
85/// The state of the Fluent_parser ensures that it will not attempt to parse
86/// object2 or object3 if the parsing of object1 failed. Thus, the user does not
87/// have to check for errors in this case. Fewer errors to check can make the
88/// user code simpler and safer.
89///
90/// There are also special member functions that provide support for common
91/// patterns in string formats:
92///
93/// - read_repeated_with_separators: Reads repeatedly into an object, skipping
94/// literal separators between reads, and optionally skipping literal
95/// separators before the first and/or after the last read.
96///
97/// - end_optional: Stores the information that it is valid for the string
98/// to end at the current position. If an error occurs while parsing
99/// subsequent tokens, the error is suppressed, the position rewound to
100/// the saved position, and the state altered to "closed".
101///
102/// - next_token_only_if: If the given boolean predicate is true, temporarily
103/// closes the Fluent_parser for only the following token.
104///
105/// - check_prev_token: Invokes a given invocable. If that produces an error in
106/// the Parser, rewinds to the position just before the last parsed token
107/// (so the error message points to just before the problematic token).
108///
109/// - call_unconditionally: Invokes a given invocable, regardless of the
110/// open/closed state.
111///
112/// The Fluent_parser also holds a Format object, used when reading objects.
113///
114/// @tparam Format_t Type used for the internal Format object.
115template <Is_format Format_t>
118
119 /// Represents the execution state of the fluent parser.
120 ///
121 /// Using the fluent API amounts to a sequence of invocations of member
122 /// functions. Within this sequence, each invocation either represents one
123 /// token parsed from the string, or behaves as a modifier for the following
124 /// token, or a modifier for the preceding token. Thus, invocations can be
125 /// grouped according to which token they belong to. Accordingly, we define a
126 /// *token sequence* as a maximal, non-empty sequence of invocations of the
127 /// following member functions:
128 ///
129 /// next_token_only_if* (read|call|literal|end_optional)? check_prev_token*
130 ///
131 /// The Fluent_state tracks the open/closed state, and tracks whether
132 /// `next_token_only_if` has temporarily altered the state to closed, needing
133 /// to restore to open when the next token sequence begins.
134 // NOLINTNEXTLINE(performance-enum-size): silence clang-tidy's pointless hint
135 enum class Fluent_state {
136 /// Ready to parse tokens.
137 open,
138 /// `next_token_only_if` has temporarily closed the token, and none of
139 /// `read`/`call`/`literal`/`end_optional`/`check_prev_token` has yet been
140 /// invoked for the current token.
142 /// `next_token_only_if` has temporarily closed the token, and at least one
143 /// of `read`/`call`/`literal`/ `end_optional`/`check_prev_token` has been
144 /// invoked for the current token, but none of
145 /// `next_token_only_if`/`read`/`call`/`literal`/`end_optional` has been
146 /// invoked for the next token and thus subsequent `check_prev_token`
147 /// invocations are still to be suppressed.
149 /// All subsequent tokens are suppressed.
150 closed
151 };
152
153 /// Value used by m_backtrack_position, indicating that end_optional has not
154 /// been invoked.
155 static constexpr std::ptrdiff_t no_backtrack_position = -1;
156
157 public:
158 /// Construct a new object, wrapping the given Parser, and using the
159 /// given format when reading sub-objects.
162
163 // Delete default constructor and copy semantics; enable only move semantics.
164 Fluent_parser() = delete;
165 Fluent_parser(const Fluent_parser &) = delete;
167 Fluent_parser &operator=(const Fluent_parser &) = delete;
168 Fluent_parser &operator=(Fluent_parser &&) noexcept = default;
169 ~Fluent_parser() = default;
170
171 // ==== Special operations ====
172
173 /// Suppress the next token if `condition` is false.
174 ///
175 /// @param condition If false, the state will be "closed" while processing the
176 /// following token.
177 Self_t &next_token_only_if(bool condition) {
178 switch (m_fluent_state) {
179 case Fluent_state::last_suppressed: // Forget previous token state,
180 // execute this check.
182 [[fallthrough]];
183 case Fluent_state::open: // Execute this check.
185 break;
186 case Fluent_state::next_suppressed: // Suppress this check.
187 case Fluent_state::closed: // Suppress this check.
188 break;
189 }
190 return *this;
191 }
192
193 /// If the states is not "closed", suppress the next token if `condition`
194 /// evaluates to false.
195 ///
196 /// @param condition If this evaluates to false, the state will be "closed"
197 /// while processing the following token.
198 Self_t &next_token_only_if(const std::invocable auto &condition) {
199 return next_token_only_if(condition());
200 }
201
202 /// If the state is not "closed", invoke the given invocable. If that changes
203 /// the state of the underlying Parse_stat to not-ok, rewind the position to
204 /// before the last token.
205 ///
206 /// @param checker Invocable to invoke.
207 Self_t &check_prev_token(const std::invocable auto &checker) {
208 switch (m_fluent_state) {
209 case Fluent_state::open: // Execute this check.
210 checker();
211 if (!m_parser.is_ok()) {
213 if (m_parser.is_parse_error()) {
217 } else {
219 }
220 }
221 }
222 break;
223 case Fluent_state::last_suppressed: // Suppress this call.
224 case Fluent_state::closed: // Suppress this call.
225 break;
226 case Fluent_state::next_suppressed: // Consume suppression request,
227 // suppress this call.
229 break;
230 }
231 return *this;
232 }
233
234 /// If the state is not "closed" save the current position, and if a
235 /// subsequent invocation of a member function fails, rewind to the saved
236 /// position and suppress the error.
238 switch (m_fluent_state) {
239 case Fluent_state::last_suppressed: // Store current position.
241 [[fallthrough]];
242 case Fluent_state::open: // Store current position.
244 break;
245 case Fluent_state::next_suppressed: // Consume suppression request,
246 // suppress this call.
248 break;
249 case Fluent_state::closed: // Suppress this call.
250 break;
251 }
252 return *this;
253 }
254
255 /// Invoke the given invocable regardless o the open/closed state.
256 Self_t &call_unconditionally(const std::invocable auto &function) {
257 function();
258 return *this;
259 }
260
261 // ==== read ====
262
263 /// If the state is not "closed", read into the given object once.
264 Self_t &read(auto &obj) { return read_repeated(Repeat::one(), obj); }
265
266 /// If the state is not "closed" read into the given object once; if that
267 /// fails with parse error, restore to the previous position and suppress the
268 /// error.
269 Self_t &read_optional(auto &obj) {
270 return read_repeated(Repeat::optional(), obj);
271 }
272
273 /// If the state is not "closed" read repeatedly into the given object until
274 /// it fails. Then, if the error is parse_error, restore to the previous
275 /// position after the last successful read and suppress the error.
276 Self_t &read_any(auto &obj) { return read_repeated(Repeat::any(), obj); }
277
278 /// If the state is not "closed" read repeatedly into the given object until
279 /// it fails. Then, if the error is parse_error and at least `count` instances
280 /// were read, restore to the previous position after the last successful read
281 /// and suppress the error.
282 Self_t &read_at_least(std::size_t count, auto &obj) {
284 }
285
286 /// If the state is not "closed" read repeatedly into the given object until
287 /// `count` instances are found or it fails. If that failed with parse_error,
288 /// restore to the previous position after the last successful read and
289 /// suppress the error.
290 Self_t &read_at_most(std::size_t count, auto &obj) {
291 return read_repeated(Repeat::at_most(count), obj);
292 }
293
294 /// If the state is not "closed", read into the given object `count` times.
295 Self_t &read_exact(std::size_t count, auto &obj) {
296 return read_repeated(Repeat::exact(count), obj);
297 }
298
299 /// If the state is not "closed" read repeatedly into the given object until
300 /// `max` instances are found or it fails. If that failed with parse_error and
301 /// at least `count` instances were read, restore to the previous position
302 /// after the last successful read and suppress the error.
303 Self_t &read_range(std::size_t min, std::size_t max, auto &obj) {
304 return read_repeated(Repeat::range(min, max), obj);
305 }
306
307 /// If the state is not "closed" read with a number of repetitions specified
308 /// by the given `Is_repeat` object. If that failed with parse_error and at
309 /// least the minimum number of repetitions were read, restore to the previous
310 /// position after the last successful read and suppress the error.
311 Self_t &read_repeated(const Is_repeat auto &repeat, auto &object) {
312 return call_repeated(
313 repeat, [&] { std::ignore = m_parser.read(m_format, object); });
314 }
315
316 // ==== read_with_format ====
317
318 /// If the state is not "closed", read into the given object once.
319 Self_t &read_with_format(const auto &format, auto &obj) {
321 }
322
323 /// If the state is not "closed" read into the given object once; if that
324 /// fails with parse error, restore to the previous position and suppress the
325 /// error.
326 Self_t &read_with_format_optional(const auto &format, auto &obj) {
328 }
329
330 /// If the state is not "closed" read repeatedly into the given object until
331 /// it fails. Then, if the error is parse_error, restore to the previous
332 /// position after the last successful read and suppress the error.
333 Self_t &read_with_format_any(const auto &format, auto &obj) {
335 }
336
337 /// If the state is not "closed" read repeatedly into the given object until
338 /// it fails. Then, if the error is parse_error and at least `count` instances
339 /// were read, restore to the previous position after the last successful read
340 /// and suppress the error.
341 Self_t &read_with_format_at_least(const auto &format, std::size_t count,
342 auto &obj) {
344 }
345
346 /// If the state is not "closed" read repeatedly into the given object until
347 /// `count` instances are found or it fails. If that failed with parse_error,
348 /// restore to the previous position after the last successful read and
349 /// suppress the error.
350 Self_t &read_with_format_at_most(const auto &format, std::size_t count,
351 auto &obj) {
353 }
354
355 /// If the state is not "closed" read into the given object `count` times.
356 Self_t &read_with_format_exact(const auto &format, std::size_t count,
357 auto &obj) {
359 }
360
361 /// If the state is not "closed" read repeatedly into the given object until
362 /// `max` instances are found or it fails. If that failed with parse_error and
363 /// at least `count` instances were read, restore to the previous position
364 /// after the last successful read and suppress the error.
365 Self_t &read_with_format_range(const auto &format, std::size_t min,
366 std::size_t max, auto &obj) {
368 }
369
370 /// If the state is not "closed" read with a number of repetitions specified
371 /// by the given `Is_repeat` object. If that failed with parse_error and at
372 /// least the minimum number of repetitions were read, restore to the previous
373 /// position after the last successful read and suppress the error.
375 const Is_repeat auto &repeat,
376 auto &object) {
377 return call_repeated(repeat,
378 [&] { std::ignore = m_parser.read(format, object); });
379 }
380
381 // ==== literal ====
382
383 /// Like `read`, but skips the given string literal.
384 Self_t &literal(const std::string_view &sv) {
385 return literal_repeated(Repeat::one(), sv);
386 }
387
388 /// Like `read_optional`, but skips the given string literal.
389 Self_t &literal_optional(const std::string_view &sv) {
391 }
392
393 /// Like `read_any`, but skips the given string literal.
394 Self_t &literal_any(const std::string_view &sv) {
395 return literal_repeated(Repeat::any(), sv);
396 }
397
398 /// Like `read_at_least`, but skips the given string literal.
399 Self_t &literal_at_least(std::size_t count, const std::string_view &sv) {
401 }
402
403 /// Like `read_at_most`, but skips the given string literal.
404 Self_t &literal_at_most(std::size_t count, const std::string_view &sv) {
406 }
407
408 /// Like `read_exact`, but skips the given string literal.
409 Self_t &literal_exact(std::size_t count, const std::string_view &sv) {
411 }
412
413 /// Like `read_range`, but skips the given string literal.
414 Self_t &literal_range(std::size_t min, std::size_t max,
415 const std::string_view &sv) {
416 return literal_repeated(Repeat::range(min, max), sv);
417 }
418
419 /// Like `read_repeated`, but skips the given string literal.
420 Self_t &literal_repeated(const Is_repeat auto &repeat,
421 const std::string_view &sv) {
422 return do_call(repeat, [&] { std::ignore = m_parser.skip(m_format, sv); });
423 }
424
425 // ==== call ====
426
427 /// Like `read`, but invokes the given function instead of reading an object.
428 Self_t &call(const std::invocable auto &function) {
429 return call_repeated(Repeat::one(), function);
430 }
431
432 /// Like `read_optional`, but invokes the given function instead of reading an
433 /// object.
434 Self_t &call_optional(const std::invocable auto &function) {
435 return call_repeated(Repeat::optional(), function);
436 }
437
438 /// Like `read_any`, but invokes the given function instead of reading an
439 /// object.
440 Self_t &call_any(const std::invocable auto &function) {
441 return call_repeated(Repeat::any(), function);
442 }
443
444 /// Like `read_at_least`, but invokes the given function instead of reading an
445 /// object.
447 const std::invocable auto &function) {
448 return call_repeated(Repeat::at_least(count), function);
449 }
450
451 /// Like `read_at_most`, but invokes the given function instead of reading an
452 /// object.
453 Self_t &call_at_most(std::size_t count, const std::invocable auto &function) {
454 return call_repeated(Repeat::at_most(count), function);
455 }
456
457 /// Like `read_exact`, but invokes the given function instead of reading an
458 /// object.
459 Self_t &call_exact(std::size_t count, const std::invocable auto &function) {
460 return call_repeated(Repeat::exact(count), function);
461 }
462
463 /// Like `read_range`, but invokes the given function instead of reading an
464 /// object.
465 Self_t &call_range(std::size_t min, std::size_t max,
466 const std::invocable auto &function) {
467 return call_repeated(Repeat::range(min, max), function);
468 }
469
470 /// Like `read_repeated`, but invokes the given function instead of reading an
471 /// object.
472 Self_t &call_repeated(const Is_repeat auto &repeat,
473 const std::invocable auto &function) {
474 return do_call(repeat, function);
475 }
476
477 // ==== {read|call}_repeated_with_separators ====
478
479 /// Reads repeatedly into the given object, using the given number of
480 /// repetitions, and skipping string literals equal to the given string_view
481 /// between reads.
482 ///
483 /// @param object Object to read into.
484 ///
485 /// @param separator String separator to read between objects.
486 ///
487 /// @param repeat The range of allowed repetitions. If fewer than the minimum
488 /// number of reads succeeded, the Parser remains in error state and this
489 /// Fluent_parser is closed. If at least the minimum number of reads succeed
490 /// and a parse error occurs, the error of the Parser is suppressed and
491 /// the Fluent_parser remains open.
492 ///
493 /// @param allow_repeated_separators When a separator is expected in the input
494 /// string, this controls the number of repetitions allowed: if `no`, exactly
495 /// one instance of the separator is parsed; if `yes`, one or more separators
496 /// are parsed.
497 ///
498 /// @param leading_separators If `yes`, the separator is required before the
499 /// first read. If `no`, the first read is attempted without reading the
500 /// separator. If `optional`, a separator preceding the first read is
501 /// optional.
502 ///
503 /// @param trailing_separators If `yes`, the separator is required after the
504 /// last read. If `no`, the separator is not read after the last read. If
505 /// `optional`, a separator after the last read is optional.
507 auto &object, const std::string_view &separator,
508 const Is_repeat auto &repeat,
509 Allow_repeated_separators allow_repeated_separators,
510 Leading_separators leading_separators,
511 Trailing_separators trailing_separators) {
513 [&] { std::ignore = m_parser.read(m_format, object); }, separator,
514 repeat, allow_repeated_separators, leading_separators,
515 trailing_separators);
516 }
517
518 /// Like `read_repeated_with_separators`, but invokes a function instead of
519 /// reads into an object. @see read_repeated_with_separators.
521 const std::invocable auto &function, const std::string_view &separator,
522 const Is_repeat auto &repeat,
523 Allow_repeated_separators allow_repeated_separators,
524 Leading_separators leading_separators,
525 Trailing_separators trailing_separators) {
526 std::size_t max_separators{1};
527 if (allow_repeated_separators == Allow_repeated_separators::yes) {
528 max_separators = std::numeric_limits<std::size_t>::max();
529 }
530 auto parse_separator = [&] { literal_range(1, max_separators, separator); };
531 auto parse_leading_separator = [&] {
532 switch (leading_separators) {
534 parse_separator();
535 break;
537 break;
539 literal_range(0, max_separators, separator);
540 break;
541 }
542 };
543
544 if (trailing_separators == Trailing_separators::no) {
545 // No trailing separators: repeat (separator, call)
546 bool first = true;
547 call_repeated(repeat, [&] {
548 if (first) {
549 parse_leading_separator();
550 first = false;
551 } else {
552 parse_separator();
553 }
554 call(function);
555 });
556 } else {
557 // (Possibly optional) trailing separators: repeat (call, separator)
558 parse_leading_separator();
559 call_repeated(repeat, [&] {
560 call(function);
561 if (trailing_separators == Trailing_separators::optional)
562 end_optional();
563 parse_separator();
564 });
565 }
566
567 return *this;
568 }
569
570 private:
571 /// Invoke the given function with the given number of repetitions.
572 ///
573 /// This function performs the bookkeeping of progressing the Fluent_state, of
574 /// tracking the position before the token (used by subsequent
575 /// check_prev_token calls), and of rewinding the position to
576 /// m_backtrack_position after parse errors.
577 Self_t &do_call(const Is_repeat auto &repeat,
578 const std::invocable auto &function) {
579 switch (m_fluent_state) {
580 case Fluent_state::last_suppressed: // Forget previous token state,
581 // execute this call.
583 [[fallthrough]];
584 case Fluent_state::open: // Execute this call.
585 {
586 auto wrapped_function = [&] {
587 // Temporarily clear m_backtrack_position while invoking the function.
588 // This allows the recursively invoked function to re-use the
589 // Fluent_parser.
590 auto old_backtrack_position = m_backtrack_position;
592 function();
593 m_backtrack_position = old_backtrack_position;
594 };
595 auto before_token = m_parser.int_pos();
596 if (m_parser.call(repeat, wrapped_function) ==
598 // Restore state, just in case sub-parser reused this Fluent_parser.
600 // Update m_before_last_token.
601 m_before_last_token = before_token;
602 } else {
603 // End parsing.
605 if (m_parser.is_parse_error() &&
610 }
611 }
612 break;
613 }
614 case Fluent_state::next_suppressed: // Consume suppression request,
615 // suppress this call.
617 break;
618 case Fluent_state::closed: // Suppress this call.
619 break;
620 }
621 return *this;
622 }
623
624 /// Format used to parse objects.
625 Format_t m_format;
626
627 /// Underlying Parser that this Fluent_parser operates on.
629
630 /// Previous position we parsed to at which it is OK to stop parsing in
631 /// case a parse error occurs. Set by `end_optional`.
633
634 /// Position before the last parsed token. Used if `check_prev_token` sets an
635 /// error state.
636 std::ptrdiff_t m_before_last_token{0};
637
638 /// The open/closed state.
640}; // Fluent_parser
641
642} // namespace mysql::strconv
643
644// addtogroup GroupLibsMysqlStrconv
645/// @}
646
647#endif // ifndef MYSQL_STRCONV_DECODE_FLUENT_PARSER_H
Fluent API for parsing strings.
Definition: fluent_parser.h:116
Self_t & call_any(const std::invocable auto &function)
Like read_any, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:440
std::ptrdiff_t m_before_last_token
Position before the last parsed token.
Definition: fluent_parser.h:636
Self_t & literal_at_least(std::size_t count, const std::string_view &sv)
Like read_at_least, but skips the given string literal.
Definition: fluent_parser.h:399
Self_t & literal_optional(const std::string_view &sv)
Like read_optional, but skips the given string literal.
Definition: fluent_parser.h:389
Self_t & read_with_format_optional(const auto &format, auto &obj)
If the state is not "closed" read into the given object once; if that fails with parse error,...
Definition: fluent_parser.h:326
Self_t & read_with_format_any(const auto &format, auto &obj)
If the state is not "closed" read repeatedly into the given object until it fails.
Definition: fluent_parser.h:333
std::ptrdiff_t m_backtrack_position
Previous position we parsed to at which it is OK to stop parsing in case a parse error occurs.
Definition: fluent_parser.h:632
Self_t & literal(const std::string_view &sv)
Like read, but skips the given string literal.
Definition: fluent_parser.h:384
Parser & m_parser
Underlying Parser that this Fluent_parser operates on.
Definition: fluent_parser.h:628
Self_t & call_repeated(const Is_repeat auto &repeat, const std::invocable auto &function)
Like read_repeated, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:472
Self_t & next_token_only_if(const std::invocable auto &condition)
If the states is not "closed", suppress the next token if condition evaluates to false.
Definition: fluent_parser.h:198
Self_t & read_repeated_with_separators(auto &object, const std::string_view &separator, const Is_repeat auto &repeat, Allow_repeated_separators allow_repeated_separators, Leading_separators leading_separators, Trailing_separators trailing_separators)
Reads repeatedly into the given object, using the given number of repetitions, and skipping string li...
Definition: fluent_parser.h:506
Self_t & call_at_least(std::size_t count, const std::invocable auto &function)
Like read_at_least, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:446
Fluent_state
Represents the execution state of the fluent parser.
Definition: fluent_parser.h:135
@ closed
All subsequent tokens are suppressed.
@ next_suppressed
next_token_only_if has temporarily closed the token, and none of read/call/literal/end_optional/check...
@ last_suppressed
next_token_only_if has temporarily closed the token, and at least one of read/call/literal/ end_optio...
Self_t & read_with_format(const auto &format, auto &obj)
If the state is not "closed", read into the given object once.
Definition: fluent_parser.h:319
Self_t & read_any(auto &obj)
If the state is not "closed" read repeatedly into the given object until it fails.
Definition: fluent_parser.h:276
Self_t & read_optional(auto &obj)
If the state is not "closed" read into the given object once; if that fails with parse error,...
Definition: fluent_parser.h:269
Self_t & next_token_only_if(bool condition)
Suppress the next token if condition is false.
Definition: fluent_parser.h:177
Self_t & read_exact(std::size_t count, auto &obj)
If the state is not "closed", read into the given object count times.
Definition: fluent_parser.h:295
Self_t & call_exact(std::size_t count, const std::invocable auto &function)
Like read_exact, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:459
Self_t & read_with_format_at_most(const auto &format, std::size_t count, auto &obj)
If the state is not "closed" read repeatedly into the given object until count instances are found or...
Definition: fluent_parser.h:350
Self_t & read_with_format_exact(const auto &format, std::size_t count, auto &obj)
If the state is not "closed" read into the given object count times.
Definition: fluent_parser.h:356
Self_t & read_repeated(const Is_repeat auto &repeat, auto &object)
If the state is not "closed" read with a number of repetitions specified by the given Is_repeat objec...
Definition: fluent_parser.h:311
Fluent_parser(const Fluent_parser &)=delete
Self_t & do_call(const Is_repeat auto &repeat, const std::invocable auto &function)
Invoke the given function with the given number of repetitions.
Definition: fluent_parser.h:577
Self_t & literal_repeated(const Is_repeat auto &repeat, const std::string_view &sv)
Like read_repeated, but skips the given string literal.
Definition: fluent_parser.h:420
Self_t & call_repeated_with_separators(const std::invocable auto &function, const std::string_view &separator, const Is_repeat auto &repeat, Allow_repeated_separators allow_repeated_separators, Leading_separators leading_separators, Trailing_separators trailing_separators)
Like read_repeated_with_separators, but invokes a function instead of reads into an object.
Definition: fluent_parser.h:520
Self_t & literal_range(std::size_t min, std::size_t max, const std::string_view &sv)
Like read_range, but skips the given string literal.
Definition: fluent_parser.h:414
Self_t & call_range(std::size_t min, std::size_t max, const std::invocable auto &function)
Like read_range, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:465
Fluent_parser(Parser &parser, const Format_t &format)
Construct a new object, wrapping the given Parser, and using the given format when reading sub-object...
Definition: fluent_parser.h:160
Self_t & end_optional()
If the state is not "closed" save the current position, and if a subsequent invocation of a member fu...
Definition: fluent_parser.h:237
Self_t & check_prev_token(const std::invocable auto &checker)
If the state is not "closed", invoke the given invocable.
Definition: fluent_parser.h:207
Self_t & read_with_format_repeated(const auto &format, const Is_repeat auto &repeat, auto &object)
If the state is not "closed" read with a number of repetitions specified by the given Is_repeat objec...
Definition: fluent_parser.h:374
Fluent_state m_fluent_state
The open/closed state.
Definition: fluent_parser.h:639
Self_t & read_at_most(std::size_t count, auto &obj)
If the state is not "closed" read repeatedly into the given object until count instances are found or...
Definition: fluent_parser.h:290
Self_t & read_at_least(std::size_t count, auto &obj)
If the state is not "closed" read repeatedly into the given object until it fails.
Definition: fluent_parser.h:282
Self_t & call_unconditionally(const std::invocable auto &function)
Invoke the given invocable regardless o the open/closed state.
Definition: fluent_parser.h:256
Self_t & literal_any(const std::string_view &sv)
Like read_any, but skips the given string literal.
Definition: fluent_parser.h:394
Self_t & read_with_format_range(const auto &format, std::size_t min, std::size_t max, auto &obj)
If the state is not "closed" read repeatedly into the given object until max instances are found or i...
Definition: fluent_parser.h:365
Format_t m_format
Format used to parse objects.
Definition: fluent_parser.h:625
Self_t & read(auto &obj)
If the state is not "closed", read into the given object once.
Definition: fluent_parser.h:264
Self_t & read_with_format_at_least(const auto &format, std::size_t count, auto &obj)
If the state is not "closed" read repeatedly into the given object until it fails.
Definition: fluent_parser.h:341
static constexpr std::ptrdiff_t no_backtrack_position
Value used by m_backtrack_position, indicating that end_optional has not been invoked.
Definition: fluent_parser.h:155
Fluent_parser(Fluent_parser &&) noexcept=default
Self_t & call_optional(const std::invocable auto &function)
Like read_optional, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:434
Self_t & call_at_most(std::size_t count, const std::invocable auto &function)
Like read_at_most, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:453
Self_t & read_range(std::size_t min, std::size_t max, auto &obj)
If the state is not "closed" read repeatedly into the given object until max instances are found or i...
Definition: fluent_parser.h:303
Self_t & call(const std::invocable auto &function)
Like read, but invokes the given function instead of reading an object.
Definition: fluent_parser.h:428
Self_t & literal_exact(std::size_t count, const std::string_view &sv)
Like read_exact, but skips the given string literal.
Definition: fluent_parser.h:409
Self_t & literal_at_most(std::size_t count, const std::string_view &sv)
Like read_at_most, but skips the given string literal.
Definition: fluent_parser.h:404
Object used to parse strings.
Definition: parser.h:69
Return_status_t call(const std::invocable auto &func)
Parse using the given function, using empty parse options.
Definition: parser.h:377
Return_status_t read(const Is_parse_options auto &opt, Object_t &obj)
Parse into the given object.
Definition: parser.h:225
void skip(const Is_parse_options_optional auto &opt, const std::string_view &sv)
Skip occurrences of the literal string sv, if found.
Definition: parser.h:125
static Repeat range(Int_t min_arg, Int_t max_arg)
Return a Repeat object representing a range of at least min_arg and at most max_arg repetitions.
Definition: repeat.h:157
static Repeat exact(std::integral auto count)
Return a Repeat object representing exactly the given number of repetitions.
Definition: repeat.h:163
static Repeat at_least(Int_t min_arg)
Return a Repeat object representing min_arg or more repetitions (bounded only by std::numeric_limits)
Definition: repeat.h:145
static Repeat one()
Return a Repeat object representing exactly one repetition.
Definition: repeat.h:168
std::size_t int_pos() const
Return the current position as an integer.
Definition: parse_position.h:107
void set_int_pos(std::size_t int_pos_arg)
Set the position to the given one.
Definition: parse_position.h:101
void revert_parse_error_to_ok() noexcept
Definition: parse_result.h:47
void update_parse_error_pos(std::size_t position)
Update the position of a parse error to the given position.
Definition: parse_result.h:58
bool is_parse_error() const
Return true if a parse error occurred.
Definition: parse_result.h:126
bool is_ok() const
Return true if the last operation succeeded, i.e., either a full match was requested and an object wa...
Definition: parse_result.h:97
static Repeat_optional at_most(std::integral auto max_arg)
Return a Repeat object representing between 0 and min_arg repetitions.
Definition: repeat.h:58
static Repeat_optional any()
Return a Repeat_optional object representing any number of repetitions from 0 and up (bounded only by...
Definition: repeat.h:64
static Repeat_optional optional()
Return a Repeat_optional object representing zero or one instances.
Definition: repeat.h:52
True if Test is either Repeat or Repeat_optional.
Definition: repeat.h:180
static const char separator
Definition: item_func.cc:4532
static int count
Definition: myisam_ftdump.cc:45
struct Parser parser
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
ValueType max(X &&first)
Definition: gtid.h:103
Definition: gtid_binary_format.h:41
Allow_repeated_separators
Used in read_repeated_with_separators: if yes, the separator may be repeated more than once whenever ...
Definition: fluent_parser.h:46
Leading_separators
Used in read_repeated_with_separators: if yes, the string must start with a separator; if no,...
Definition: fluent_parser.h:50
Trailing_separators
Used in read_repeated_with_separators: if yes, the string must end with a separator; if no,...
Definition: fluent_parser.h:54
@ ok
operation succeeded
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Experimental API header.
Experimental API header.
Experimental API header.