1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief An very small, simple and somewhat limited implementation of
8  * recursive-descent parser.
9  *
10  * @since v.0.6.1
11  */
12 
13 #pragma once
14 
15 #include <restinio/impl/to_lower_lut.hpp>
16 #include <restinio/impl/overflow_controlled_integer_accumulator.hpp>
17 
18 #include <restinio/utils/tuple_algorithms.hpp>
19 #include <restinio/utils/metaprogramming.hpp>
20 
21 #include <restinio/string_view.hpp>
22 #include <restinio/compiler_features.hpp>
23 
24 #include <restinio/exception.hpp>
25 #include <restinio/optional.hpp>
26 #include <restinio/expected.hpp>
27 
28 #include <iostream>
29 #include <limits>
30 #include <map>
31 #include <array>
32 #include <vector>
33 #include <cstring>
34 
35 namespace restinio
36 {
37 
38 namespace easy_parser
39 {
40 
41 namespace meta = restinio::utils::metaprogramming;
42 
43 //
44 // error_reason_t
45 //
46 /*!
47  * @brief Reason of parsing error.
48  *
49  * @since v.0.6.1
50  */
51 enum class error_reason_t
52 {
53 	//! Unexpected character is found in the input.
54 	unexpected_character,
55 	//! Unexpected end of input is encontered when some character expected.
56 	unexpected_eof,
57 	//! None of alternatives was found in the input.
58 	no_appropriate_alternative,
59 	//! Required pattern is not found in the input.
60 	pattern_not_found,
61 	//! There are some unconsumed non-whitespace characters in the input
62 	//! after the completion of parsing.
63 	unconsumed_input,
64 	//! Illegal value was found in the input.
65 	/*!
66 	 * @since v.0.6.2
67 	 */
68 	illegal_value_found,
69 	//! A failure of parsing an alternative marked as "force only this
70 	//! alternative".
71 	/*!
72 	 * This error code is intended for internal use for the implementation
73 	 * of alternatives() and force_only_this_alternative() stuff.
74 	 *
75 	 * This error tells the parser that other alternatives should not be
76 	 * checked and the parsing of the whole alternatives clause should
77 	 * failed too.
78 	 *
79 	 * @since v.0.6.7
80 	 */
81 	force_only_this_alternative_failed
82 };
83 
84 //
85 // parse_error_t
86 //
87 /*!
88  * @brief Information about parsing error.
89  *
90  * @since v.0.6.1
91  */
92 class parse_error_t
93 {
94 	//! Position in the input stream.
95 	std::size_t m_position;
96 	//! The reason of the error.
97 	error_reason_t m_reason;
98 
99 public:
100 	//! Initializing constructor.
parse_error_t(std::size_t position,error_reason_t reason)101 	parse_error_t(
102 		std::size_t position,
103 		error_reason_t reason ) noexcept
104 		:	m_position{ position }
105 		,	m_reason{ reason }
106 	{}
107 
108 	//! Get the position in the input stream where error was detected.
109 	RESTINIO_NODISCARD
110 	std::size_t
position() const111 	position() const noexcept { return m_position; }
112 
113 	//! Get the reason of the error.
114 	RESTINIO_NODISCARD
115 	error_reason_t
reason() const116 	reason() const noexcept { return m_reason; }
117 };
118 
119 //
120 // nothing_t
121 //
122 /*!
123  * @brief A special type to be used in the case where there is no
124  * need to store produced value.
125  *
126  * @since v.0.6.1
127  */
128 struct nothing_t {};
129 
130 //
131 // result_value_wrapper
132 //
133 /*!
134  * @brief A template with specializations for different kind
135  * of result values and for type `nothing`.
136  *
137  * Every specialization for a case when T is not a container should have the
138  * following content:
139  * @code
140  * struct result_value_wrapper<...>
141  * {
142  * 	using result_type = ... // type of the result value.
143  * 	using wrapped_type = ... // type to be created inside a producer
144  * 		// to hold a temporary value during the parsing.
145  *
146  * 	static void
147  * 	as_result( wrapped_type & to, result_type && what );
148  *
149  * 	RESTINIO_NODISCARD static result_type &&
150  * 	unwrap_value( wrapped_type & from );
151  * };
152  * @endcode
153  *
154  * Every specialization for a case when T is a container should have
155  * the following content:
156  * @code
157  * struct result_value_wrapper<...>
158  * {
159  * 	using result_type = ... // type of the result value.
160  * 	using value_type = ... // type of object to be placed into a container
161  * 		// if result_type is a container.
162  * 	using wrapped_type = ... // type to be created inside a producer
163  * 		// to hold a temporary value during the parsing.
164  *
165  * 	static void
166  * 	as_result( wrapped_type & to, result_type && what );
167  *
168  * 	static void
169  * 	to_container( wrapped_type & to, value_type && item );
170  *
171  * 	RESTINIO_NODISCARD static result_type &&
172  * 	unwrap_value( wrapped_type & from );
173  * };
174  * @endcode
175  *
176  * @since v.0.6.6
177  */
178 template< typename T >
179 struct result_value_wrapper
180 {
181 	using result_type = T;
182 	using wrapped_type = result_type;
183 
184 	static void
as_resultrestinio::easy_parser::result_value_wrapper185 	as_result( wrapped_type & to, result_type && what )
186 	{
187 		to = std::move(what);
188 	}
189 
190 	RESTINIO_NODISCARD
191 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper192 	unwrap_value( wrapped_type & v )
193 	{
194 		return std::move(v);
195 	}
196 };
197 
198 //
199 // result_wrapper_for
200 //
201 /*!
202  * @brief A metafunction for detection of actual result_value_wrapper
203  * type for T
204  *
205  * If a specialization of result_value_wrapper defines wrapped_type
206  * as a different type from result_type then transform() and consume()
207  * methods will receive a reference to wrapped_type. And there will be
208  * a task to detect actual result_type from a wrapped_type.
209  *
210  * To solve this task it is necessary to have a way to get
211  * result_value_wrapper<result_type> from wrapped_type.
212  *
213  * This metafunction is that way.
214  *
215  * @note
216  * For each specialization of result_value_wrapper<T> that introduces
217  * wrapped_type different from result_type a specialization of
218  * result_wrapper_for should also be provided. For example:
219  * @code
220  * class my_type {...};
221  * class my_type_wrapper { ... };
222  *
223  * namespace restinio {
224  * namespace easy_parser {
225  *
226  * template<>
227  * struct result_value_wrapper<my_type> {
228  * 	using result_type = my_type;
229  * 	using wrapped_type = my_type_wrapper;
230  * 	...
231  * };
232  * template<>
233  * struct result_wrapper_for<my_type_wrapper> {
234  * 	using type = result_value_wrapper<my_type>;
235  * };
236  *
237  * } // namespace easy_parser
238  * } // namespace restinio
239  * @endcode
240  *
241  * @since v.0.6.6
242  */
243 template< typename T >
244 struct result_wrapper_for
245 {
246 	using type = result_value_wrapper< T >;
247 };
248 
249 template< typename T >
250 using result_wrapper_for_t = typename result_wrapper_for<T>::type;
251 
252 template< typename T, typename... Args >
253 struct result_value_wrapper< std::vector< T, Args... > >
254 {
255 	using result_type = std::vector< T, Args... >;
256 	using value_type = typename result_type::value_type;
257 	using wrapped_type = result_type;
258 
259 	static void
as_resultrestinio::easy_parser::result_value_wrapper260 	as_result( wrapped_type & to, result_type && what )
261 	{
262 		to = std::move(what);
263 	}
264 
265 	static void
to_containerrestinio::easy_parser::result_value_wrapper266 	to_container( wrapped_type & to, value_type && what )
267 	{
268 		to.push_back( std::move(what) );
269 	}
270 
271 	RESTINIO_NODISCARD
272 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper273 	unwrap_value( wrapped_type & v )
274 	{
275 		return std::move(v);
276 	}
277 };
278 
279 namespace impl
280 {
281 
282 //
283 // std_array_wrapper
284 //
285 /*!
286  * @brief A special wrapper for std::array type to be used inside
287  * a producer during the parsing.
288  *
289  * This type is intended to be used inside a specialization of
290  * result_value_wrapper for std::array.
291  *
292  * This type holds the current index that can be used by
293  * to_container method for addition of a new item to the result array.
294  *
295  * @since v.0.6.6
296  */
297 template< typename T, std::size_t S >
298 struct std_array_wrapper
299 {
300 	std::array< T, S > m_array;
301 	std::size_t m_index{ 0u };
302 };
303 
304 } /* namespace impl */
305 
306 template< typename T, std::size_t S >
307 struct result_value_wrapper< std::array< T, S > >
308 {
309 	using result_type = std::array< T, S >;
310 	using value_type = typename result_type::value_type;
311 	using wrapped_type = impl::std_array_wrapper< T, S >;
312 
313 	static void
as_resultrestinio::easy_parser::result_value_wrapper314 	as_result( wrapped_type & to, result_type && what )
315 	{
316 		to.m_array = std::move(what);
317 		to.m_index = 0u;
318 	}
319 
320 	static void
to_containerrestinio::easy_parser::result_value_wrapper321 	to_container( wrapped_type & to, value_type && what )
322 	{
323 		if( to.m_index >= S )
324 			throw exception_t(
325 					"index in the result std::array is out of range, "
326 					"index=" + std::to_string(to.m_index) +
327 					", size={}" + std::to_string(S) );
328 
329 		to.m_array[ to.m_index ] = std::move(what);
330 		++to.m_index;
331 	}
332 
333 	RESTINIO_NODISCARD
334 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper335 	unwrap_value( wrapped_type & v )
336 	{
337 		return std::move(v.m_array);
338 	}
339 };
340 
341 /*!
342  * @brief A specialization of result_wrapper_for metafunction for
343  * the case of std::array wrapper.
344  *
345  * @since v.0.6.6
346  */
347 template< typename T, std::size_t S >
348 struct result_wrapper_for< impl::std_array_wrapper<T, S> >
349 {
350 	using type = result_value_wrapper< std::array< T, S > >;
351 };
352 
353 template< typename Char, typename... Args >
354 struct result_value_wrapper< std::basic_string< Char, Args... > >
355 {
356 	using result_type = std::basic_string< Char, Args... >;
357 	using value_type = Char;
358 	using wrapped_type = result_type;
359 
360 	static void
as_resultrestinio::easy_parser::result_value_wrapper361 	as_result( wrapped_type & to, result_type && what )
362 	{
363 		to = std::move(what);
364 	}
365 
366 	static void
to_containerrestinio::easy_parser::result_value_wrapper367 	to_container( wrapped_type & to, value_type && what )
368 	{
369 		to.push_back( what );
370 	}
371 
372 	/*!
373 	 * @brief Special overload for the case when std::string should
374 	 * be added to another std::string.
375 	 *
376 	 * For example, in cases like:
377 	 * @code
378 	 * produce< std::string >(
379 	 * 	produce< std::string >(...) >> to_container(),
380 	 * 	produce< std::string >(...) >> to_container(),
381 	 * 	...
382 	 * )
383 	 * @endcode
384 	 */
385 	static void
to_containerrestinio::easy_parser::result_value_wrapper386 	to_container( wrapped_type & to, wrapped_type && what )
387 	{
388 		to.append( what );
389 	}
390 
391 	RESTINIO_NODISCARD
392 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper393 	unwrap_value( wrapped_type & v )
394 	{
395 		return std::move(v);
396 	}
397 };
398 
399 template< typename K, typename V, typename... Args >
400 struct result_value_wrapper< std::map< K, V, Args... > >
401 {
402 	using result_type = std::map< K, V, Args... >;
403 	// NOTE: we can't use container_type::value_type here
404 	// because value_type for std::map is std::pair<const K, V>,
405 	// not just std::pair<K, V>,
406 	using value_type = std::pair<K, V>;
407 	using wrapped_type = result_type;
408 
409 	static void
as_resultrestinio::easy_parser::result_value_wrapper410 	as_result( wrapped_type & to, result_type && what )
411 	{
412 		to = std::move(what);
413 	}
414 
415 	static void
to_containerrestinio::easy_parser::result_value_wrapper416 	to_container( wrapped_type & to, value_type && what )
417 	{
418 		to.emplace( std::move(what) );
419 	}
420 
421 	RESTINIO_NODISCARD
422 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper423 	unwrap_value( wrapped_type & v )
424 	{
425 		return std::move(v);
426 	}
427 };
428 
429 template<>
430 struct result_value_wrapper< nothing_t >
431 {
432 	using result_type = nothing_t;
433 	using value_type = nothing_t;
434 	using wrapped_type = result_type;
435 
436 	static void
as_resultrestinio::easy_parser::result_value_wrapper437 	as_result( wrapped_type &, result_type && ) noexcept {}
438 
439 	static void
to_containerrestinio::easy_parser::result_value_wrapper440 	to_container( wrapped_type &, value_type && ) noexcept {}
441 
442 	RESTINIO_NODISCARD
443 	static result_type &&
unwrap_valuerestinio::easy_parser::result_value_wrapper444 	unwrap_value( wrapped_type & v )
445 	{
446 		return std::move(v);
447 	}
448 };
449 
450 /*!
451  * @brief A special marker that means infinite repetitions.
452  *
453  * @since v.0.6.1
454  */
455 constexpr std::size_t N = std::numeric_limits<std::size_t>::max();
456 
457 //
458 // digits_to_consume_t
459 //
460 /*!
461  * @brief Limits for number of digits to be extracted during
462  * parsing of decimal numbers.
463  *
464  * @since v.0.6.6
465  */
466 class digits_to_consume_t
467 {
468 public:
469 	using underlying_int_t = std::int_fast8_t;
470 
471 	//! Minimal number of digits to consume.
472 	/*!
473 	 * @note
474 	 * Can't be 0, but this value is not checked for
475 	 * performance reasons.
476 	 */
477 	underlying_int_t m_min;
478 	//! Maximal number of digits to consume.
479 	underlying_int_t m_max;
480 
481 public:
482 	/*!
483 	 * A constructor for the case when min = max and both are
484 	 * equal to @a total.
485 	 */
486 	constexpr
digits_to_consume_t(underlying_int_t total)487 	digits_to_consume_t( underlying_int_t total ) noexcept
488 		:	m_min{ total }
489 		,	m_max{ total }
490 	{}
491 
492 	/*!
493 	 * A constructor for the case when min and max are specified
494 	 * separately.
495 	 */
496 	constexpr
digits_to_consume_t(underlying_int_t min,underlying_int_t max)497 	digits_to_consume_t(
498 		underlying_int_t min,
499 		underlying_int_t max ) noexcept
500 		:	m_min{ min }
501 		,	m_max{ max }
502 	{}
503 
504 	//! Get the minimal value.
505 	RESTINIO_NODISCARD
506 	constexpr auto
min() const507 	min() const noexcept { return m_min; }
508 
509 	//! Get the maximum value.
510 	RESTINIO_NODISCARD
511 	constexpr auto
max() const512 	max() const noexcept { return m_max; }
513 
514 	//! Get the value that means that maximum is not limited.
515 	RESTINIO_NODISCARD
516 	constexpr static auto
unlimited_max()517 	unlimited_max() noexcept
518 	{
519 		return std::numeric_limits<underlying_int_t>::max();
520 	}
521 
522 	/*!
523 	 * Returns `digits_to_consume_t{1, unlimited_max()}`.
524 	 */
525 	RESTINIO_NODISCARD
526 	constexpr static auto
from_one_to_max()527 	from_one_to_max() noexcept
528 	{
529 		return digits_to_consume_t{ 1, unlimited_max() };
530 	}
531 };
532 
533 /*!
534  * @brief Create a limit for number of digits to be extracted.
535  *
536  * Makes a limit where min==max and both are equal to @a total.
537  *
538  * Usage example:
539  * @code
540  * using namespace restinio::easy_parser;
541  *
542  * auto x_uint32_p = hexadecimal_number_p<std::uint32_t>(expected_digits(8));
543  * @endcode
544  *
545  * @since v.0.6.6
546  */
547 RESTINIO_NODISCARD
548 inline constexpr digits_to_consume_t
expected_digits(digits_to_consume_t::underlying_int_t total)549 expected_digits( digits_to_consume_t::underlying_int_t total ) noexcept
550 {
551 	return { total };
552 }
553 
554 /*!
555  * @brief Create a limit for number of digits to be extracted.
556  *
557  * Makes a limit where min and max are specified separately.
558  *
559  * Usage example:
560  * @code
561  * using namespace restinio::easy_parser;
562  *
563  * auto ten_digits_int32_p = decimal_number_p<std::int32_t>(expected_digits(1, 10));
564  * @endcode
565  *
566  * @since v.0.6.6
567  */
568 RESTINIO_NODISCARD
569 inline constexpr digits_to_consume_t
expected_digits(digits_to_consume_t::underlying_int_t min,digits_to_consume_t::underlying_int_t max)570 expected_digits(
571 	digits_to_consume_t::underlying_int_t min,
572 	digits_to_consume_t::underlying_int_t max ) noexcept
573 {
574 	return { min, max };
575 }
576 
577 namespace impl
578 {
579 
580 //
581 // character_t
582 //
583 /*!
584  * @brief One character extracted from the input stream.
585  *
586  * If the characted extracted successfuly then m_eof will be `false`.
587  * If the end of input reached then m_eof is `true` and the value
588  * of m_ch is undefined.
589  *
590  * @since v.0.6.1
591  */
592 struct character_t
593 {
594 	bool m_eof;
595 	char m_ch;
596 };
597 
598 RESTINIO_NODISCARD
599 inline bool
operator ==(const character_t & a,const character_t & b)600 operator==( const character_t & a, const character_t & b ) noexcept
601 {
602 	return (a.m_eof == b.m_eof && a.m_ch == b.m_ch);
603 }
604 
605 RESTINIO_NODISCARD
606 inline bool
operator !=(const character_t & a,const character_t & b)607 operator!=( const character_t & a, const character_t & b ) noexcept
608 {
609 	return (a.m_eof != b.m_eof || a.m_ch != b.m_ch);
610 }
611 
612 /*!
613  * @brief A constant for SPACE value.
614  *
615  * @since v.0.6.1
616  */
617 constexpr char SP = ' ';
618 /*!
619  * @brief A constant for Horizontal Tab value.
620  *
621  * @since v.0.6.1
622  */
623 constexpr char	HTAB = '\x09';
624 
625 //
626 // is_space
627 //
628 /*!
629  * @brief If a character a space character?
630  *
631  * @since v.0.6.1
632  */
633 RESTINIO_NODISCARD
634 inline constexpr bool
is_space(const char ch)635 is_space( const char ch ) noexcept
636 {
637 	return ch == SP || ch == HTAB;
638 }
639 
640 //
641 // is_space_predicate_t
642 //
643 /*!
644  * @brief A preducate for symbol_producer_template that checks that
645  * a symbol is a space.
646  *
647  * @since v.0.6.4
648  */
649 struct is_space_predicate_t
650 {
651 	RESTINIO_NODISCARD
652 	bool
operator ()restinio::easy_parser::impl::is_space_predicate_t653 	operator()( const char actual ) const noexcept
654 	{
655 		return is_space(actual);
656 	}
657 };
658 
659 //
660 // is_digit
661 //
662 /*!
663  * @brief Is a character a decimal digit?
664  *
665  * @since v.0.6.1
666  */
667 RESTINIO_NODISCARD
668 inline constexpr bool
is_digit(const char ch)669 is_digit( const char ch ) noexcept
670 {
671 	return (ch >= '0' && ch <= '9');
672 }
673 
674 //
675 // is_digit_predicate_t
676 //
677 /*!
678  * @brief A predicate for cases where char to be expected to be a decimal digit.
679  *
680  * @since v.0.6.6
681  */
682 struct is_digit_predicate_t
683 {
684 	RESTINIO_NODISCARD
685 	bool
operator ()restinio::easy_parser::impl::is_digit_predicate_t686 	operator()( const char actual ) const noexcept
687 	{
688 		return is_digit( actual );
689 	}
690 };
691 
692 //
693 // is_hexdigit
694 //
695 /*!
696  * @brief Is a character a hexadecimal digit?
697  *
698  * @since v.0.6.6
699  */
700 RESTINIO_NODISCARD
701 inline constexpr bool
is_hexdigit(const char ch)702 is_hexdigit( const char ch ) noexcept
703 {
704 	return (ch >= '0' && ch <= '9') ||
705 			(ch >= 'A' && ch <= 'F') ||
706 			(ch >= 'a' && ch <= 'f');
707 }
708 
709 //
710 // is_hexdigit_predicate_t
711 //
712 /*!
713  * @brief A predicate for cases where char to be expected
714  * to be a hexadecimal digit.
715  *
716  * @since v.0.6.6
717  */
718 struct is_hexdigit_predicate_t
719 {
720 	RESTINIO_NODISCARD
721 	bool
operator ()restinio::easy_parser::impl::is_hexdigit_predicate_t722 	operator()( const char actual ) const noexcept
723 	{
724 		return is_hexdigit( actual );
725 	}
726 };
727 
728 //
729 // source_t
730 //
731 /*!
732  * @brief The class that implements "input stream".
733  *
734  * It is expected that string_view passed to the constructor of
735  * source_t will outlive the instance of source_t.
736  *
737  * @since v.0.6.1
738  */
739 class source_t
740 {
741 	//! The content to be used as "input stream".
742 	const string_view_t m_data;
743 	//! The current position in the input stream.
744 	/*!
745 	 * \note
746 	 * m_index can have value of m_data.size(). In that case
747 	 * EOF will be returned.
748 	 */
749 	string_view_t::size_type m_index{};
750 
751 public:
752 	//! Type to be used as the index inside the input stream.
753 	using position_t = string_view_t::size_type;
754 
755 	//! Initializing constructor.
source_t(string_view_t data)756 	explicit source_t( string_view_t data ) noexcept : m_data{ data } {}
757 
758 	//! Get the next character from the input stream.
759 	/*!
760 	 * EOF can be returned in the case if there is no more data in
761 	 * the input stream.
762 	 */
763 	RESTINIO_NODISCARD
764 	character_t
getch()765 	getch() noexcept
766 	{
767 		if( m_index < m_data.size() )
768 		{
769 			return {false, m_data[ m_index++ ]};
770 		}
771 		else
772 			return {true, 0};
773 	}
774 
775 	//! Return one character back to the input stream.
776 	void
putback()777 	putback() noexcept
778 	{
779 		if( m_index )
780 			--m_index;
781 	}
782 
783 	//! Get the current position in the stream.
784 	RESTINIO_NODISCARD
785 	position_t
current_position() const786 	current_position() const noexcept
787 	{
788 		return m_index;
789 	}
790 
791 	//! Return the current position in the input stream
792 	//! at the specified position.
793 	void
backto(position_t pos)794 	backto( position_t pos ) noexcept
795 	{
796 		if( pos <= m_data.size() )
797 			m_index = pos;
798 	}
799 
800 	//! Is EOF has been reached?
801 	RESTINIO_NODISCARD
802 	bool
eof() const803 	eof() const noexcept
804 	{
805 		return m_index >= m_data.size();
806 	}
807 
808 	//! Return a fragment from the input stream.
809 	/*!
810 	 * \attention
811 	 * The value of \a from should be lesser than the size of the
812 	 * input stream.
813 	 */
814 	RESTINIO_NODISCARD
815 	string_view_t
fragment(string_view_t::size_type from,string_view_t::size_type length=string_view_t::npos) const816 	fragment(
817 		//! Starting position for the fragment required.
818 		string_view_t::size_type from,
819 		//! Length of the fragment required.
820 		//! Value string_view_t::npos means the whole remaining content
821 		//! of the input stream starting from position \a from.
822 		string_view_t::size_type length = string_view_t::npos ) const noexcept
823 	{
824 		return m_data.substr( from, length );
825 	}
826 
827 	/*!
828 	 * @brief A helper class to automatically return acquired
829 	 * content back to the input stream.
830 	 *
831 	 * Usage example:
832 	 * @code
833 	 * expected_t<result_type, parse_error_t> try_parse(source_t & from) {
834 	 * 	source_t::content_consumer_t consumer{from};
835 	 * 	for(auto ch = from.getch(); some_condition(ch); ch = from.getch())
836 	 * 	{
837 	 * 		... // do something with ch.
838 	 * 	}
839 	 * 	if(no_errors_detected())
840 	 * 		// All acquired content should be consumed.
841 	 * 		consumer.commit();
842 	 *
843 	 * 	// Otherwise all acquired content will be returned back to the input stream.
844 	 * 	...
845 	 * }
846 	 * @endcode
847 	 *
848 	 * @since v.0.6.1
849 	 */
850 	class content_consumer_t
851 	{
852 		source_t & m_from;
853 		const position_t m_started_at;
854 		bool m_consumed{ false };
855 
856 	public :
857 		content_consumer_t() = delete;
858 		content_consumer_t( const content_consumer_t & ) = delete;
859 		content_consumer_t( content_consumer_t && ) = delete;
860 
content_consumer_t(source_t & from)861 		content_consumer_t( source_t & from ) noexcept
862 			:	m_from{ from }
863 			,	m_started_at{ from.current_position() }
864 		{}
865 
~content_consumer_t()866 		~content_consumer_t() noexcept
867 		{
868 			if( !m_consumed )
869 				m_from.backto( m_started_at );
870 		}
871 
872 		position_t
started_at() const873 		started_at() const noexcept
874 		{
875 			return m_started_at;
876 		}
877 
878 		//! Consume all acquired content.
879 		/*!
880 		 * @note
881 		 * If that method is not called then all acquired content
882 		 * will be returned back.
883 		 */
884 		void
commit()885 		commit() noexcept
886 		{
887 			m_consumed = true;
888 		}
889 	};
890 };
891 
892 //
893 // entity_type_t
894 //
895 /*!
896  * @brief A marker for distinguish different kind of entities in parser.
897  *
898  * @since v.0.6.1
899  */
900 enum class entity_type_t
901 {
902 	//! Entity is a producer of values.
903 	producer,
904 	//! Entity is a transformer of a value from one type to another.
905 	transformer,
906 	//! Entity is a consumer of values. It requires a value on the input
907 	//! and doesn't produces anything.
908 	consumer,
909 	//! Entity is a clause. It doesn't produces anything.
910 	clause,
911 	//! Entity is a transformer-proxy. It can't be used directly, only
912 	//! for binding a producer and transformer together.
913 	/*!
914 	 * @since v.0.6.6.
915 	 */
916 	transformer_proxy
917 };
918 
919 //
920 // producer_tag
921 //
922 /*!
923  * @brief A special base class to be used with producers.
924  *
925  * Every producer class should have the following content:
926  *
927  * @code
928  * class some_producer_type
929  * {
930  * public:
931  * 	using result_type = ... // some producer-specific type.
932  * 	static constexpr entity_type_t entity_type = entity_type_t::producer;
933  *
934  * 	expected_t<result_type, parse_error_t>
935  * 	try_parse(source_t & from);
936  *
937  * 	...
938  * };
939  * @endcode
940  *
941  * @since v.0.6.1
942  */
943 template< typename Result_Type >
944 struct producer_tag
945 {
946 	using result_type = Result_Type;
947 	static constexpr entity_type_t entity_type = entity_type_t::producer;
948 };
949 
950 template< typename T, typename = meta::void_t<> >
951 struct is_producer : public std::false_type {};
952 
953 template< typename T >
954 struct is_producer< T, meta::void_t< decltype(T::entity_type) > >
955 {
956 	static constexpr bool value = entity_type_t::producer == T::entity_type;
957 };
958 
959 /*!
960  * @brief A meta-value to check whether T is a producer type.
961  *
962  * @note
963  * The current implementation checks only the presence of T::entity_type of
964  * type entity_type_t and the value of T::entity_type. Presence of
965  * T::result_type and T::try_parse is not checked.
966  *
967  * @since v.0.6.1
968  */
969 template< typename T >
970 constexpr bool is_producer_v = is_producer<T>::value;
971 
972 //
973 // transformer_tag
974 //
975 /*!
976  * @brief A special base class to be used with transformers.
977  *
978  * Every transformer class should have the following content:
979  *
980  * @code
981  * class some_transformer_type
982  * {
983  * public:
984  * 	using result_type = ... // some transformer-specific type.
985  * 	static constexpr entity_type_t entity_type = entity_type_t::transformer;
986  *
987  * 	result_type
988  * 	transform(Input_Type && from);
989  *
990  * 	...
991  * };
992  * @endcode
993  * where `Input_Type` is transformer's specific types.
994  *
995  * @since v.0.6.1
996  */
997 template< typename Result_Type >
998 struct transformer_tag
999 {
1000 	using result_type = Result_Type;
1001 	static constexpr entity_type_t entity_type = entity_type_t::transformer;
1002 };
1003 
1004 template< typename T, typename = meta::void_t<> >
1005 struct is_transformer : public std::false_type {};
1006 
1007 template< typename T >
1008 struct is_transformer< T, meta::void_t< decltype(T::entity_type) > >
1009 {
1010 	static constexpr bool value = entity_type_t::transformer == T::entity_type;
1011 };
1012 
1013 /*!
1014  * @brief A meta-value to check whether T is a transformer type.
1015  *
1016  * @note
1017  * The current implementation checks only the presence of T::entity_type of
1018  * type entity_type_t and the value of T::entity_type. Presence of
1019  * T::result_type and T::transform is not checked.
1020  *
1021  * @since v.0.6.1
1022  */
1023 template< typename T >
1024 constexpr bool is_transformer_v = is_transformer<T>::value;
1025 
1026 //
1027 // transformer_invoker
1028 //
1029 /*!
1030  * @brief A helper template for calling transformation function.
1031  *
1032  * The transformer_invoker class is intended to wrap a call to
1033  * @a Transformer::transform method. That method can return
1034  * a value of type T or a value of type expected_t<T, error_reason_t>.
1035  *
1036  * In the case of return value of type T the returned value of T
1037  * should be used directly.
1038  *
1039  * In the case of return value of type expected_t<T, error_reason_t>
1040  * the return value should be checked for the presence of an error.
1041  * In the case of an error expected_t<T, error_reason_t> should be
1042  * converted into expected_t<T, parser_error_t>.
1043  *
1044  * @since v.0.6.11
1045  */
1046 template< typename Result_Type >
1047 struct transformer_invoker
1048 {
1049 	template< typename Transformer, typename Input_Type >
1050 	RESTINIO_NODISCARD
1051 	static Result_Type
invokerestinio::easy_parser::impl::transformer_invoker1052 	invoke(
1053 		source_t &,
1054 		Transformer & transformer,
1055 		expected_t< Input_Type, parse_error_t > && input )
1056 	{
1057 		return transformer.transform( std::move(*input) );
1058 	}
1059 };
1060 
1061 /*!
1062  * This specialization of transformer_invoker handles a case when
1063  * transformation method returns expected_t<T, error_reason_t>.
1064  *
1065  * @since v.0.6.11
1066  */
1067 template< typename Result_Type >
1068 struct transformer_invoker< expected_t< Result_Type, error_reason_t > >
1069 {
1070 	template< typename Transformer, typename Input_Type >
1071 	RESTINIO_NODISCARD
1072 	static expected_t< Result_Type, parse_error_t >
invokerestinio::easy_parser::impl::transformer_invoker1073 	invoke(
1074 		// source_t is necessary to get the position in the case of an error.
1075 		source_t & source,
1076 		Transformer & transformer,
1077 		expected_t< Input_Type, parse_error_t > && input )
1078 	{
1079 		auto result = transformer.transform( std::move(*input) );
1080 		if( result )
1081 			return *result;
1082 		else
1083 			return make_unexpected( parse_error_t{
1084 					source.current_position(),
1085 					result.error()
1086 				} );
1087 	}
1088 };
1089 
1090 //
1091 // is_appropriate_transformer_result_type
1092 //
1093 /*!
1094  * @brief A metafunction that checks is Result_Type can be used as
1095  * the result of transformation method.
1096  *
1097  * A transformation method can return a value of type T or a value
1098  * of type expected_t<T, error_reason_t>. But a user can define
1099  * transformation method that returns an expected_t<T, parse_error_t>
1100  * just by a mistake. That mistake should be detected.
1101  *
1102  * Metafunction is_appropriate_transformer_result_type serves that
1103  * purpose: it defines @a value to `true` if transformation method
1104  * returns T or expected_t<T, error_reason_t>. In the case of
1105  * expected_t<T, parse_error_t> @a value will be set to `false.
1106  *
1107  * @since v.0.6.11
1108  */
1109 template< typename Result_Type >
1110 struct is_appropriate_transformer_result_type
1111 {
1112 	static constexpr bool value = true;
1113 };
1114 
1115 template< typename Result_Type >
1116 struct is_appropriate_transformer_result_type<
1117 		expected_t< Result_Type, error_reason_t > >
1118 {
1119 	static constexpr bool value = true;
1120 };
1121 
1122 template< typename Result_Type >
1123 struct is_appropriate_transformer_result_type<
1124 		expected_t< Result_Type, parse_error_t > >
1125 {
1126 	static constexpr bool value = false;
1127 };
1128 
1129 //
1130 // transformed_value_producer_traits_checker
1131 //
1132 /*!
1133  * @brief A helper template for checking a possibility to connect
1134  * a producer with a transformer.
1135  *
1136  * This helper can be seen as a metafunction that defines a boolean
1137  * value is_valid_transformation_result_type. If that value is `true`
1138  * then @a Transformer::transform method returns allowed type
1139  * (T or expected_t<T, error_reson_t>).
1140  *
1141  * @since v.0.6.11
1142  */
1143 template< typename Producer, typename Transformer >
1144 struct transformed_value_producer_traits_checker
1145 {
1146 	static_assert( is_producer_v<Producer>,
1147 			"Producer should be a producer type" );
1148 	static_assert( is_transformer_v<Transformer>,
1149 			"Transformer should be a transformer type" );
1150 
1151 	using producer_result_t = std::decay_t< decltype(
1152 			std::declval<Producer &>().try_parse( std::declval<source_t &>() )
1153 		) >;
1154 
1155 	using transformation_result_t = std::decay_t< decltype(
1156 			std::declval<Transformer &>().transform(
1157 					std::move(*(std::declval<producer_result_t>())) )
1158 		) >;
1159 
1160 	using expected_result_t = typename Transformer::result_type;
1161 
1162 	static constexpr bool is_valid_transformation_result_type =
1163 			is_appropriate_transformer_result_type< expected_result_t >::value;
1164 };
1165 
1166 //
1167 // transformed_value_producer_t
1168 //
1169 /*!
1170  * @brief A template of producer that gets a value from another
1171  * producer, transforms it and produces transformed value.
1172  *
1173  * @tparam Producer the type of producer of source value.
1174  * @tparam Transformer the type of transformer from source to the target value.
1175  *
1176  * @since v.0.6.1
1177  */
1178 template< typename Producer, typename Transformer >
1179 class transformed_value_producer_t
1180 	:	public producer_tag< typename Transformer::result_type >
1181 {
1182 	using traits_checker = transformed_value_producer_traits_checker<
1183 			Producer, Transformer >;
1184 
1185 	static_assert(
1186 			traits_checker::is_valid_transformation_result_type,
1187 			"transformation result should be either T or "
1188 			"expected_t<T, error_reson_t>, not expected_t<T, parse_error_t>" );
1189 
1190 	Producer m_producer;
1191 	Transformer m_transformer;
1192 
1193 public :
1194 	using result_type = typename Transformer::result_type;
1195 
transformed_value_producer_t(Producer && producer,Transformer && transformer)1196 	transformed_value_producer_t(
1197 		Producer && producer,
1198 		Transformer && transformer )
1199 		:	m_producer{ std::move(producer) }
1200 		,	m_transformer{ std::move(transformer) }
1201 	{}
1202 
1203 	RESTINIO_NODISCARD
1204 	expected_t< result_type, parse_error_t >
try_parse(source_t & source)1205 	try_parse( source_t & source )
1206 	{
1207 		auto producer_result = m_producer.try_parse( source );
1208 		if( producer_result )
1209 		{
1210 			using transformation_result_t =
1211 					typename traits_checker::transformation_result_t;
1212 
1213 			return transformer_invoker< transformation_result_t >::invoke(
1214 					source,
1215 					m_transformer,
1216 					std::move(producer_result) );
1217 		}
1218 		else
1219 			return make_unexpected( producer_result.error() );
1220 	}
1221 };
1222 
1223 /*!
1224  * @brief A special operator to connect a value producer with value transformer.
1225  *
1226  * @since v.0.6.1
1227  */
1228 template< typename P, typename T >
1229 RESTINIO_NODISCARD
1230 std::enable_if_t<
1231 	is_producer_v<P> & is_transformer_v<T>,
1232 	transformed_value_producer_t< P, T > >
operator >>(P producer,T transformer)1233 operator>>(
1234 	P producer,
1235 	T transformer )
1236 {
1237 	using transformator_type = transformed_value_producer_t< P, T >;
1238 
1239 	return transformator_type{ std::move(producer), std::move(transformer) };
1240 }
1241 
1242 //
1243 // transformer_proxy_tag
1244 //
1245 /*!
1246  * @brief A special base class to be used with transformer-proxies.
1247  *
1248  * Every transformer-proxy class should have the following content:
1249  *
1250  * @code
1251  * class some_transformer_proxy_type
1252  * {
1253  * public:
1254  * 	static constexpr entity_type_t entity_type = entity_type_t::transformer;
1255  *
1256  * 	template< typename Input_Type >
1257  * 	auto
1258  * 	make_transformer();
1259  * 	...
1260  * };
1261  * @endcode
1262  * where `Input_Type` is will be specified by a producer.
1263  *
1264  * @since v.0.6.6
1265  */
1266 struct transformer_proxy_tag
1267 {
1268 	static constexpr entity_type_t entity_type = entity_type_t::transformer_proxy;
1269 };
1270 
1271 template< typename T, typename = meta::void_t<> >
1272 struct is_transformer_proxy : public std::false_type {};
1273 
1274 template< typename T >
1275 struct is_transformer_proxy< T, meta::void_t< decltype(T::entity_type) > >
1276 {
1277 	static constexpr bool value = entity_type_t::transformer_proxy == T::entity_type;
1278 };
1279 
1280 /*!
1281  * @brief A meta-value to check whether T is a transformer-proxy type.
1282  *
1283  * @note
1284  * The current implementation checks only the presence of T::entity_type of
1285  * type entity_type_t and the value of T::entity_type.
1286  *
1287  * @since v.0.6.6
1288  */
1289 template< typename T >
1290 constexpr bool is_transformer_proxy_v = is_transformer_proxy<T>::value;
1291 
1292 /*!
1293  * @brief A special operator to connect a value producer with value transformer
1294  * via transformer-proxy.
1295  *
1296  * @since v.0.6.6
1297  */
1298 template<
1299 	typename P,
1300 	typename T,
1301 	typename S = std::enable_if_t<
1302 			is_producer_v<P> & is_transformer_proxy_v<T>,
1303 			void > >
1304 RESTINIO_NODISCARD
1305 auto
operator >>(P producer,T transformer_proxy)1306 operator>>(
1307 	P producer,
1308 	T transformer_proxy )
1309 {
1310 	auto real_transformer = transformer_proxy.template make_transformer<
1311 			typename P::result_type >();
1312 
1313 	using transformator_type = std::decay_t< decltype(real_transformer) >;
1314 
1315 	using producer_type = transformed_value_producer_t< P, transformator_type >;
1316 
1317 	return producer_type{ std::move(producer), std::move(real_transformer) };
1318 }
1319 
1320 //
1321 // consumer_tag
1322 //
1323 /*!
1324  * @brief A special base class to be used with consumers.
1325  *
1326  * Every consumer class should have the following content:
1327  *
1328  * @code
1329  * class some_consumer_type
1330  * {
1331  * public :
1332  * 	static constexpr entity_type_t entity_type = entity_type_t::consumer;
1333  *
1334  * 	void consume( Target_Type & dest, Value && current_value );
1335  * 	...
1336  * };
1337  * @endcode
1338  * where `Target_Type` and `Value` are consumer's specific types.
1339  *
1340  * @since v.0.6.1
1341  */
1342 struct consumer_tag
1343 {
1344 	static constexpr entity_type_t entity_type = entity_type_t::consumer;
1345 };
1346 
1347 template< typename T, typename = meta::void_t<> >
1348 struct is_consumer : public std::false_type {};
1349 
1350 template< typename T >
1351 struct is_consumer< T, meta::void_t< decltype(T::entity_type) > >
1352 {
1353 	static constexpr bool value = entity_type_t::consumer == T::entity_type;
1354 };
1355 
1356 /*!
1357  * @brief A meta-value to check whether T is a consumer type.
1358  *
1359  * @note
1360  * The current implementation checks only the presence of T::entity_type of
1361  * type entity_type_t and the value of T::entity_type. Presence of
1362  * T::consume is not checked.
1363  *
1364  * @since v.0.6.1
1365  */
1366 template< typename T >
1367 constexpr bool is_consumer_v = is_consumer<T>::value;
1368 
1369 //
1370 // clause_tag
1371 //
1372 /*!
1373  * @brief A special base class to be used with clauses.
1374  *
1375  * Every clause class should have the following content:
1376  *
1377  * @code
1378  * class some_consumer_type
1379  * {
1380  * public :
1381  * 	static constexpr entity_type_t entity_type = entity_type_t::clause;
1382  *
1383  * 	optional_t<parse_error_t>
1384  * 	try_process(source_t & from, Target_Type & dest);
1385  * 	...
1386  * };
1387  * @endcode
1388  * where `Target_Type` is clause's specific types.
1389  *
1390  * @since v.0.6.1
1391  */
1392 struct clause_tag
1393 {
1394 	static constexpr entity_type_t entity_type = entity_type_t::clause;
1395 };
1396 
1397 template< typename T, typename = meta::void_t<> >
1398 struct is_clause : public std::false_type {};
1399 
1400 template< typename T >
1401 struct is_clause< T, meta::void_t<
1402 	decltype(std::decay_t<T>::entity_type) > >
1403 {
1404 	using real_type = std::decay_t<T>;
1405 
1406 	static constexpr bool value = entity_type_t::clause == real_type::entity_type;
1407 };
1408 
1409 /*!
1410  * @brief A meta-value to check whether T is a consumer type.
1411  *
1412  * @note
1413  * The current implementation checks only the presence of T::entity_type of
1414  * type entity_type_t and the value of T::entity_type. Presence of
1415  * T::try_process is not checked.
1416  *
1417  * @since v.0.6.1
1418  */
1419 template< typename T >
1420 constexpr bool is_clause_v = is_clause<T>::value;
1421 
1422 //
1423 // tuple_of_entities_t
1424 //
1425 /*!
1426  * @brief A helper meta-function to create an actual type of tuple
1427  * with clauses/producers.
1428  *
1429  * Usage example:
1430  * @code
1431  * template< typename... Clauses >
1432  * auto
1433  * some_clause( Clauses && ...clauses ) {
1434  * 	using clause_type = impl::some_clause_t<
1435  * 			impl::tuple_of_entities_t<Clauses...> >;
1436  * 	return clause_type{ std::forward<Clauses>(clauses)... };
1437  * }
1438  * @endcode
1439  *
1440  * The tuple_of_entities_t takes care about such cases as references and
1441  * constness of parameters. For example:
1442  * @code
1443  * auto c = symbol('c');
1444  * const auto b = symbol('b');
1445  * auto clause = some_clause(c, b);
1446  * @endcode
1447  * In that case `Clauses...` will be `symbol_clause_t&, const
1448  * symbol_clause_t&`. And an attempt to make type `std::tuple<Clauses...>` will
1449  * produce type `std::tuple<symbol_clause_t&, const symbol_clause_t&>`. But we
1450  * need `std::tuple<symbol_clause_t, symbol_clause_t>`. This result will be
1451  * obtained if `tuple_of_entities_t` is used instead of `std::tuple`.
1452  *
1453  * @since v.0.6.6
1454  */
1455 template< typename... Entities >
1456 using tuple_of_entities_t = meta::rename_t<
1457 		meta::transform_t< std::decay, meta::type_list<Entities...> >,
1458 		std::tuple >;
1459 
1460 //
1461 // consume_value_clause_t
1462 //
1463 /*!
1464  * @brief A template for a clause that binds a value producer with value
1465  * consumer.
1466  *
1467  * @tparam P the type of value producer.
1468  * @tparam C the type of value consumer.
1469  *
1470  * @since v.0.6.1
1471  */
1472 template< typename P, typename C >
1473 class consume_value_clause_t : public clause_tag
1474 {
1475 	static_assert( is_producer_v<P>, "P should be a producer type" );
1476 	static_assert( is_consumer_v<C>, "C should be a consumer type" );
1477 
1478 	P m_producer;
1479 	C m_consumer;
1480 
1481 public :
consume_value_clause_t(P && producer,C && consumer)1482 	consume_value_clause_t( P && producer, C && consumer )
1483 		:	m_producer{ std::move(producer) }
1484 		,	m_consumer{ std::move(consumer) }
1485 	{}
1486 
1487 	template< typename Target_Type >
1488 	RESTINIO_NODISCARD
1489 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & target)1490 	try_process( source_t & from, Target_Type & target )
1491 	{
1492 		auto parse_result = m_producer.try_parse( from );
1493 		if( parse_result )
1494 		{
1495 			m_consumer.consume( target, std::move(*parse_result) );
1496 			return nullopt;
1497 		}
1498 		else
1499 			return parse_result.error();
1500 	}
1501 };
1502 
1503 /*!
1504  * @brief A special operator to connect a value producer with a value consumer.
1505  *
1506  * @since v.0.6.1
1507  */
1508 template< typename P, typename C >
1509 RESTINIO_NODISCARD
1510 std::enable_if_t<
1511 	is_producer_v<P> && is_consumer_v<C>,
1512 	consume_value_clause_t< P, C > >
operator >>(P producer,C consumer)1513 operator>>( P producer, C consumer )
1514 {
1515 	return { std::move(producer), std::move(consumer) };
1516 }
1517 
1518 //
1519 // top_level_clause_t
1520 //
1521 /*!
1522  * @brief A special class to be used as the top level clause in parser.
1523  *
1524  * @note
1525  * That class doesn't look like an ordinal clause and can't be connected
1526  * with other clauses. Method try_process has the different format and
1527  * returns the value of Producer::try_parse.
1528  *
1529  * @since v.0.6.1
1530  */
1531 template< typename Producer >
1532 class top_level_clause_t
1533 {
1534 	static_assert( is_producer_v<Producer>,
1535 			"Producer should be a producer type" );
1536 
1537 	Producer m_producer;
1538 
1539 public :
top_level_clause_t(Producer && producer)1540 	top_level_clause_t( Producer && producer )
1541 		:	m_producer{ std::move(producer) }
1542 	{}
1543 
1544 	RESTINIO_NODISCARD
1545 	auto
try_process(source_t & from)1546 	try_process( source_t & from )
1547 	{
1548 		return m_producer.try_parse( from );
1549 	}
1550 };
1551 
1552 //
1553 // ensure_no_remaining_content
1554 //
1555 /*!
1556  * @brief A special function to check that there is no more actual
1557  * data in the input stream except whitespaces.
1558  *
1559  * @return parse_error_t if some non-whitespace character is found
1560  * in the input stream.
1561  *
1562  * @since v.0.6.1
1563  */
1564 RESTINIO_NODISCARD
1565 inline optional_t< parse_error_t >
ensure_no_remaining_content(source_t & from)1566 ensure_no_remaining_content(
1567 	source_t & from )
1568 {
1569 	while( !from.eof() )
1570 	{
1571 		if( !is_space( from.getch().m_ch ) )
1572 		{
1573 			from.putback(); // Otherwise current_position() will be wrong.
1574 			return parse_error_t{
1575 					from.current_position(),
1576 					error_reason_t::unconsumed_input
1577 			};
1578 		}
1579 	}
1580 
1581 	return nullopt;
1582 }
1583 
1584 //
1585 // remove_trailing_spaces
1586 //
1587 /*!
1588  * @brief Helper function for removal of trailing spaces from a string-view.
1589  *
1590  * @since v.0.6.7
1591  */
1592 RESTINIO_NODISCARD
1593 inline string_view_t
remove_trailing_spaces(string_view_t from)1594 remove_trailing_spaces( string_view_t from ) noexcept
1595 {
1596 	auto s = from.size();
1597 	for(; s && is_space( from[ (s-1u) ] ); --s) {}
1598 
1599 	return from.substr( 0u, s );
1600 }
1601 
1602 //
1603 // alternatives_clause_t
1604 //
1605 /*!
1606  * @brief A template for implementation of clause that selects one of
1607  * alternative clauses.
1608  *
1609  * This template implements rules like:
1610    @verbatim
1611    T := A | B | C
1612    @endverbatim
1613  *
1614  * It works very simple way:
1615  *
1616  * - `try_process` for the first alternative is called. If it fails then...
1617  * - `try_process` for the second alternative is called. If it fails then...
1618  * - `try_process` for the third alternative is called...
1619  * - and so on.
1620  *
1621  * If no one of alternatives is selected then the current position in
1622  * the input stream is restored.
1623  *
1624  * @note
1625  * The copy of Target_Type object passed to `try_process` method is
1626  * created before checking each alternative.
1627  *
1628  * @tparam Subitems_Tuple the type of std::tuple with items for every
1629  * alternative clauses.
1630  *
1631  * @since v.0.6.1
1632  */
1633 template<
1634 	typename Subitems_Tuple >
1635 class alternatives_clause_t : public clause_tag
1636 {
1637 	Subitems_Tuple m_subitems;
1638 
1639 public :
alternatives_clause_t(Subitems_Tuple && subitems)1640 	alternatives_clause_t(
1641 		Subitems_Tuple && subitems )
1642 		:	m_subitems{ std::move(subitems) }
1643 	{}
1644 
1645 	template< typename Target_Type >
1646 	RESTINIO_NODISCARD
1647 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & target)1648 	try_process( source_t & from, Target_Type & target )
1649 	{
1650 		const auto starting_pos = from.current_position();
1651 
1652 		optional_t< parse_error_t > actual_parse_error;
1653 		const bool success = restinio::utils::tuple_algorithms::any_of(
1654 				m_subitems,
1655 				[&from, &target, &actual_parse_error]( auto && one_producer ) {
1656 					source_t::content_consumer_t consumer{ from };
1657 					Target_Type tmp_value{ target };
1658 
1659 					actual_parse_error = one_producer.try_process( from, tmp_value );
1660 					if( !actual_parse_error )
1661 					{
1662 						target = std::move(tmp_value);
1663 						consumer.commit();
1664 
1665 						return true;
1666 					}
1667 					else {
1668 						// Since v.0.6.7 we should check for
1669 						// force_only_this_alternative_failed error.
1670 						// In the case of that error enumeration of alternatives
1671 						// should be stopped.
1672 						return error_reason_t::force_only_this_alternative_failed ==
1673 								actual_parse_error->reason();
1674 					}
1675 				} );
1676 
1677 		if( !success || actual_parse_error )
1678 			return parse_error_t{
1679 					starting_pos,
1680 					error_reason_t::no_appropriate_alternative
1681 			};
1682 		else
1683 			return nullopt;
1684 	}
1685 };
1686 
1687 //
1688 // maybe_clause_t
1689 //
1690 /*!
1691  * @brief A template for implementation of clause that checks and
1692  * handles presence of optional entity in the input stream.
1693  *
1694  * This template implements rules like:
1695    @verbatim
1696    T := [ A B C ]
1697    @endverbatim
1698  *
1699  * @note
1700  * The copy of Target_Type object passed to `try_process` method is
1701  * created before checking the presence of subitems. If all subitems
1702  * are found then the value of that temporary object moved back to
1703  * \a target parameter of `try_process` method.
1704  *
1705  * @note
1706  * This clause always returns success even if nothing has been
1707  * consumed from the input stream.
1708  *
1709  * @tparam Subitems_Tuple the type of std::tuple with items for every
1710  * clause to be checked.
1711  *
1712  * @since v.0.6.1
1713  */
1714 template<
1715 	typename Subitems_Tuple >
1716 class maybe_clause_t : public clause_tag
1717 {
1718 	Subitems_Tuple m_subitems;
1719 
1720 public :
maybe_clause_t(Subitems_Tuple && subitems)1721 	maybe_clause_t(
1722 		Subitems_Tuple && subitems )
1723 		:	m_subitems{ std::move(subitems) }
1724 	{}
1725 
1726 	template< typename Target_Type >
1727 	RESTINIO_NODISCARD
1728 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & target)1729 	try_process( source_t & from, Target_Type & target )
1730 	{
1731 		source_t::content_consumer_t consumer{ from };
1732 		Target_Type tmp_value{ target };
1733 
1734 		const bool success = restinio::utils::tuple_algorithms::all_of(
1735 				m_subitems,
1736 				[&from, &tmp_value]( auto && one_producer ) {
1737 					return !one_producer.try_process( from, tmp_value );
1738 				} );
1739 
1740 		if( success )
1741 		{
1742 			target = std::move(tmp_value);
1743 			consumer.commit();
1744 		}
1745 
1746 		// maybe_clause always returns success even if nothing consumed.
1747 		return nullopt;
1748 	}
1749 };
1750 
1751 //
1752 // not_clause_t
1753 //
1754 /*!
1755  * @brief A template for implementation of clause that checks absence of
1756  * some entity in the input stream.
1757  *
1758  * This template implements rules like:
1759    @verbatim
1760 	T := !A B
1761    @endverbatim
1762  * where not_clause_t is related to the part `!A` only.
1763  *
1764  * @note
1765  * The empty temporary object of Target_Type passed to call of `try_process` of
1766  * subitems.
1767  *
1768  * @note
1769  * This clause always returns the current position in the input stream
1770  * back at the position where this clause was called.
1771  *
1772  * @tparam Subitems_Tuple the type of std::tuple with items for every
1773  * clause to be checked.
1774  *
1775  * @since v.0.6.1
1776  */
1777 template<
1778 	typename Subitems_Tuple >
1779 class not_clause_t : public clause_tag
1780 {
1781 	Subitems_Tuple m_subitems;
1782 
1783 public :
not_clause_t(Subitems_Tuple && subitems)1784 	not_clause_t(
1785 		Subitems_Tuple && subitems )
1786 		:	m_subitems{ std::move(subitems) }
1787 	{}
1788 
1789 	template< typename Target_Type >
1790 	RESTINIO_NODISCARD
1791 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type &)1792 	try_process( source_t & from, Target_Type & )
1793 	{
1794 		// NOTE: will always return the current position back.
1795 		source_t::content_consumer_t consumer{ from };
1796 
1797 		Target_Type dummy_value;
1798 
1799 		const auto success = !restinio::utils::tuple_algorithms::all_of(
1800 				m_subitems,
1801 				[&from, &dummy_value]( auto && one_producer ) {
1802 					return !one_producer.try_process( from, dummy_value );
1803 				} );
1804 
1805 		// This is contra-intuitive but: we return pattern_not_found in
1806 		// the case when pattern is actually found in the input.
1807 		if( !success )
1808 			return parse_error_t{
1809 					consumer.started_at(),
1810 					//FIXME: maybe a more appropriate error_reason can
1811 					//be used here?
1812 					error_reason_t::pattern_not_found
1813 			};
1814 		else
1815 			return nullopt;
1816 	}
1817 };
1818 
1819 //
1820 // and_clause_t
1821 //
1822 /*!
1823  * @brief A template for implementation of clause that checks the presence of
1824  * some entity in the input stream.
1825  *
1826  * This template implements rules like:
1827    @verbatim
1828 	T := A &B
1829    @endverbatim
1830  * where and_clause_t is related to the part `&B` only.
1831  *
1832  * @note
1833  * The empty temporary object of Target_Type passed to call of `try_process` of
1834  * subitems.
1835  *
1836  * @note
1837  * This clause always returns the current position in the input stream
1838  * back at the position where this clause was called.
1839  *
1840  * @tparam Subitems_Tuple the type of std::tuple with items for every
1841  * clause to be checked.
1842  *
1843  * @since v.0.6.1
1844  */
1845 template<
1846 	typename Subitems_Tuple >
1847 class and_clause_t : public clause_tag
1848 {
1849 	Subitems_Tuple m_subitems;
1850 
1851 public :
and_clause_t(Subitems_Tuple && subitems)1852 	and_clause_t(
1853 		Subitems_Tuple && subitems )
1854 		:	m_subitems{ std::move(subitems) }
1855 	{}
1856 
1857 	template< typename Target_Type >
1858 	RESTINIO_NODISCARD
1859 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type &)1860 	try_process( source_t & from, Target_Type & )
1861 	{
1862 		// NOTE: will always return the current position back.
1863 		source_t::content_consumer_t consumer{ from };
1864 
1865 		Target_Type dummy_value;
1866 
1867 		const bool success = restinio::utils::tuple_algorithms::all_of(
1868 				m_subitems,
1869 				[&from, &dummy_value]( auto && one_producer ) {
1870 					return !one_producer.try_process( from, dummy_value );
1871 				} );
1872 
1873 		if( !success )
1874 			return parse_error_t{
1875 					consumer.started_at(),
1876 					error_reason_t::pattern_not_found
1877 			};
1878 		else
1879 			return nullopt;
1880 	}
1881 };
1882 
1883 //
1884 // sequence_clause_t
1885 //
1886 /*!
1887  * @brief A template for implementation of clause that checks and
1888  * handles presence of sequence of entities in the input stream.
1889  *
1890  * This template implements rules like:
1891    @verbatim
1892    T := A B C
1893    @endverbatim
1894  *
1895  * @note
1896  * The copy of Target_Type object passed to `try_process` method is
1897  * created before checking the presence of subitems. If all subitems
1898  * are found then the value of that temporary object moved back to
1899  * @a target parameter of `try_process` method.
1900  *
1901  * @tparam Subitems_Tuple the type of std::tuple with items for every
1902  * clause to be checked.
1903  *
1904  * @since v.0.6.1
1905  */
1906 template<
1907 	typename Subitems_Tuple >
1908 class sequence_clause_t : public clause_tag
1909 {
1910 	Subitems_Tuple m_subitems;
1911 
1912 public :
sequence_clause_t(Subitems_Tuple && subitems)1913 	sequence_clause_t(
1914 		Subitems_Tuple && subitems )
1915 		:	m_subitems{ std::move(subitems) }
1916 	{}
1917 
1918 	template< typename Target_Type >
1919 	RESTINIO_NODISCARD
1920 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & target)1921 	try_process( source_t & from, Target_Type & target )
1922 	{
1923 		source_t::content_consumer_t consumer{ from };
1924 		Target_Type tmp_value{ target };
1925 
1926 		// We should store actual parse error from subitems to return it.
1927 		optional_t< parse_error_t > result;
1928 
1929 		const bool success = restinio::utils::tuple_algorithms::all_of(
1930 				m_subitems,
1931 				[&from, &tmp_value, &result]( auto && one_producer ) {
1932 					result = one_producer.try_process( from, tmp_value );
1933 					return !result;
1934 				} );
1935 
1936 		if( success )
1937 		{
1938 			target = std::move(tmp_value);
1939 			consumer.commit();
1940 		}
1941 
1942 		return result;
1943 	}
1944 };
1945 
1946 //
1947 // forced_alternative_clause_t
1948 //
1949 /*!
1950  * @brief An alternative that should be parsed correctly or the parsing
1951  * of the whole alternatives clause should fail.
1952  *
1953  * This special clause is intended to be used in the implementation
1954  * of restinio::easy_parser::force_only_this_alternative(). See the
1955  * description of that function for more details.
1956  *
1957  * @since v.0.6.7
1958  */
1959 template<
1960 	typename Subitems_Tuple >
1961 class forced_alternative_clause_t : public sequence_clause_t< Subitems_Tuple >
1962 {
1963 	using base_type_t = sequence_clause_t< Subitems_Tuple >;
1964 
1965 public :
1966 	using base_type_t::base_type_t;
1967 
1968 	template< typename Target_Type >
1969 	RESTINIO_NODISCARD
1970 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & target)1971 	try_process( source_t & from, Target_Type & target )
1972 	{
1973 		const auto starting_pos = from.current_position();
1974 
1975 		if( base_type_t::try_process( from, target ) )
1976 		{
1977 			// The forced clause is not parsed correctly.
1978 			// So the special error code should be returned in that case.
1979 			return parse_error_t{
1980 					starting_pos,
1981 					error_reason_t::force_only_this_alternative_failed
1982 			};
1983 		}
1984 		else
1985 			return nullopt;
1986 	}
1987 };
1988 
1989 //
1990 // produce_t
1991 //
1992 /*!
1993  * @brief A template for producing a value of specific type of
1994  * a sequence of entities from the input stream.
1995  *
1996  * Creates a new empty object of type Target_Type in `try_parse` and
1997  * then call `try_process` methods for every subitems. A reference to
1998  * that new object is passed to every `try_process` call.
1999  *
2000  * @tparam Target_Type the type of value to be produced.
2001  * @tparam Subitems_Tuple the type of std::tuple with items for every
2002  * clause to be checked.
2003  *
2004  * @since v.0.6.1
2005  */
2006 template<
2007 	typename Target_Type,
2008 	typename Subitems_Tuple >
2009 class produce_t : public producer_tag< Target_Type >
2010 {
2011 	using value_wrapper_t = result_value_wrapper< Target_Type >;
2012 
2013 	Subitems_Tuple m_subitems;
2014 
2015 public :
produce_t(Subitems_Tuple && subitems)2016 	produce_t(
2017 		Subitems_Tuple && subitems )
2018 		:	m_subitems{ std::move(subitems) }
2019 	{}
2020 
2021 	RESTINIO_NODISCARD
2022 	expected_t< Target_Type, parse_error_t >
try_parse(source_t & from)2023 	try_parse( source_t & from )
2024 	{
2025 		typename value_wrapper_t::wrapped_type tmp_value{};
2026 		optional_t< parse_error_t > error;
2027 
2028 		const bool success = restinio::utils::tuple_algorithms::all_of(
2029 				m_subitems,
2030 				[&from, &tmp_value, &error]( auto && one_clause ) {
2031 					error = one_clause.try_process( from, tmp_value );
2032 					return !error;
2033 				} );
2034 
2035 		if( success )
2036 			return value_wrapper_t::unwrap_value( tmp_value );
2037 		else
2038 			return make_unexpected( *error );
2039 	}
2040 };
2041 
2042 //
2043 // repeat_clause_t
2044 //
2045 /*!
2046  * @brief A template for handling repetition of clauses.
2047  *
2048  * Calls `try_process` for all subitems until some of them returns
2049  * error or max_occurences will be passed.
2050  *
2051  * Returns failure if min_occurences wasn't passed.
2052  *
2053  * @tparam Subitems_Tuple the type of std::tuple with items for every
2054  * clause to be checked.
2055  *
2056  * @since v.0.6.1
2057  */
2058 template<
2059 	typename Subitems_Tuple >
2060 class repeat_clause_t : public clause_tag
2061 {
2062 	std::size_t m_min_occurences;
2063 	std::size_t m_max_occurences;
2064 
2065 	Subitems_Tuple m_subitems;
2066 
2067 public :
repeat_clause_t(std::size_t min_occurences,std::size_t max_occurences,Subitems_Tuple && subitems)2068 	repeat_clause_t(
2069 		std::size_t min_occurences,
2070 		std::size_t max_occurences,
2071 		Subitems_Tuple && subitems )
2072 		:	m_min_occurences{ min_occurences }
2073 		,	m_max_occurences{ max_occurences }
2074 		,	m_subitems{ std::move(subitems) }
2075 	{}
2076 
2077 	template< typename Target_Type >
2078 	RESTINIO_NODISCARD
2079 	optional_t< parse_error_t >
try_process(source_t & from,Target_Type & dest)2080 	try_process( source_t & from, Target_Type & dest )
2081 	{
2082 		source_t::content_consumer_t whole_consumer{ from };
2083 
2084 		std::size_t count{};
2085 		bool failure_detected{ false };
2086 		for(; !failure_detected && count != m_max_occurences; )
2087 		{
2088 			source_t::content_consumer_t item_consumer{ from };
2089 
2090 			failure_detected = !restinio::utils::tuple_algorithms::all_of(
2091 					m_subitems,
2092 					[&from, &dest]( auto && one_clause ) {
2093 						return !one_clause.try_process( from, dest );
2094 					} );
2095 
2096 			if( !failure_detected )
2097 			{
2098 				// Another item successfully parsed and should be stored.
2099 				item_consumer.commit();
2100 				++count;
2101 			}
2102 		}
2103 
2104 		if( count >= m_min_occurences )
2105 		{
2106 			whole_consumer.commit();
2107 			return nullopt;
2108 		}
2109 
2110 		return parse_error_t{
2111 				from.current_position(),
2112 				error_reason_t::pattern_not_found
2113 		};
2114 	}
2115 };
2116 
2117 //
2118 // symbol_producer_template_t
2119 //
2120 /*!
2121  * @brief A template for producer of charachers that satisfy some predicate.
2122  *
2123  * In the case of success returns the expected character.
2124  *
2125  * @tparam Predicate the type of predicate to check extracted symbol.
2126  *
2127  * @since v.0.6.1
2128  */
2129 template< typename Predicate >
2130 class symbol_producer_template_t
2131 	:	public producer_tag< char >
2132 	,	protected Predicate
2133 {
2134 public:
2135 	template< typename... Args >
symbol_producer_template_t(Args &&...args)2136 	symbol_producer_template_t( Args &&... args )
2137 		:	 Predicate{ std::forward<Args>(args)... }
2138 	{}
2139 
2140 	RESTINIO_NODISCARD
2141 	expected_t< char, parse_error_t >
try_parse(source_t & from) const2142 	try_parse( source_t & from ) const noexcept
2143 	{
2144 		const auto ch = from.getch();
2145 		if( !ch.m_eof )
2146 		{
2147 			// A call to predicate.
2148 			if( (*this)(ch.m_ch) )
2149 				return ch.m_ch;
2150 			else
2151 			{
2152 				from.putback();
2153 				return make_unexpected( parse_error_t{
2154 						from.current_position(),
2155 						error_reason_t::unexpected_character
2156 				} );
2157 			}
2158 		}
2159 		else
2160 			return make_unexpected( parse_error_t{
2161 					from.current_position(),
2162 					error_reason_t::unexpected_eof
2163 			} );
2164 	}
2165 };
2166 
2167 //
2168 // any_symbol_predicate_t
2169 //
2170 /*!
2171  * @brief A predicate that allows extraction of any symbol.
2172  *
2173  * This predicate is necessary for implementation of any_symbol_p()
2174  * producer.
2175  *
2176  * @since v.0.6.6
2177  */
2178 struct any_symbol_predicate_t
2179 {
2180 	RESTINIO_NODISCARD
2181 	constexpr bool
operator ()restinio::easy_parser::impl::any_symbol_predicate_t2182 	operator()( const char ) const noexcept
2183 	{
2184 		return true;
2185 	}
2186 };
2187 
2188 //
2189 // particular_symbol_predicate_t
2190 //
2191 /*!
2192  * @brief A predicate for cases where exact match of expected and
2193  * actual symbols is required.
2194  *
2195  * @since v.0.6.1
2196  */
2197 struct particular_symbol_predicate_t
2198 {
2199 	char m_expected;
2200 
2201 	RESTINIO_NODISCARD
2202 	bool
operator ()restinio::easy_parser::impl::particular_symbol_predicate_t2203 	operator()( const char actual ) const noexcept
2204 	{
2205 		return m_expected == actual;
2206 	}
2207 };
2208 
2209 //
2210 // not_particular_symbol_predicate_t
2211 //
2212 /*!
2213  * @brief A predicate for cases where mismatch with a particular
2214  * symbol is required.
2215  *
2216  * @since v.0.6.6
2217  */
2218 struct not_particular_symbol_predicate_t
2219 {
2220 	char m_sentinel;
2221 
2222 	RESTINIO_NODISCARD
2223 	bool
operator ()restinio::easy_parser::impl::not_particular_symbol_predicate_t2224 	operator()( const char actual ) const noexcept
2225 	{
2226 		return m_sentinel != actual;
2227 	}
2228 };
2229 
2230 //
2231 // caseless_particular_symbol_predicate_t
2232 //
2233 /*!
2234  * @brief A predicate for cases where the case-insensitive match of expected
2235  * and actual symbols is required.
2236  *
2237  * @since v.0.6.6
2238  */
2239 struct caseless_particular_symbol_predicate_t
2240 {
2241 	char m_expected;
2242 
caseless_particular_symbol_predicate_trestinio::easy_parser::impl::caseless_particular_symbol_predicate_t2243 	caseless_particular_symbol_predicate_t( char v ) noexcept
2244 		:	m_expected{ restinio::impl::to_lower_case( v ) }
2245 	{}
2246 
2247 	RESTINIO_NODISCARD
2248 	bool
operator ()restinio::easy_parser::impl::caseless_particular_symbol_predicate_t2249 	operator()( const char actual ) const noexcept
2250 	{
2251 		return m_expected == restinio::impl::to_lower_case(actual);
2252 	}
2253 };
2254 
2255 //
2256 // symbol_from_range_predicate_t
2257 //
2258 /*!
2259  * @brief A predicate for cases where a symbol should belong
2260  * to specified range.
2261  *
2262  * Range is inclusive. It means that `(ch >= left && ch <= right)`.
2263  *
2264  * @since v.0.6.9
2265  */
2266 struct symbol_from_range_predicate_t
2267 {
2268 	char m_left;
2269 	char m_right;
2270 
2271 	RESTINIO_NODISCARD
2272 	bool
operator ()restinio::easy_parser::impl::symbol_from_range_predicate_t2273 	operator()( const char actual ) const noexcept
2274 	{
2275 		return ( actual >= m_left && actual <= m_right );
2276 	}
2277 };
2278 
2279 //
2280 // symbol_producer_t
2281 //
2282 /*!
2283  * @brief A producer for the case when a particual character is expected
2284  * in the input stream.
2285  *
2286  * In the case of success returns the expected character.
2287  *
2288  * @since v.0.6.1
2289  */
2290 class symbol_producer_t
2291 	: public symbol_producer_template_t< particular_symbol_predicate_t >
2292 {
2293 	using base_type_t =
2294 		symbol_producer_template_t< particular_symbol_predicate_t >;
2295 
2296 public:
symbol_producer_t(char expected)2297 	symbol_producer_t( char expected )
2298 		:	base_type_t{ particular_symbol_predicate_t{expected} }
2299 	{}
2300 };
2301 
2302 //
2303 // any_symbol_if_not_producer_t
2304 //
2305 /*!
2306  * @brief A producer for the case when any character except the specific
2307  * sentinel character is expected in the input stream.
2308  *
2309  * In the case of success returns a character from the input stream.
2310  *
2311  * @since v.0.6.6
2312  */
2313 class any_symbol_if_not_producer_t
2314 	: public symbol_producer_template_t< not_particular_symbol_predicate_t >
2315 {
2316 	using base_type_t =
2317 		symbol_producer_template_t< not_particular_symbol_predicate_t >;
2318 
2319 public:
any_symbol_if_not_producer_t(char sentinel)2320 	any_symbol_if_not_producer_t( char sentinel )
2321 		:	base_type_t{ not_particular_symbol_predicate_t{sentinel} }
2322 	{}
2323 };
2324 
2325 //
2326 // caseless_symbol_producer_t
2327 //
2328 /*!
2329  * @brief A producer for the case when a particual character is expected
2330  * in the input stream.
2331  *
2332  * Performs caseless comparison of symbols.
2333  *
2334  * In the case of success returns the character from the input stream
2335  * (e.g. without transformation to lower or upper case).
2336  *
2337  * @since v.0.6.6
2338  */
2339 class caseless_symbol_producer_t
2340 	: public symbol_producer_template_t< caseless_particular_symbol_predicate_t >
2341 {
2342 	using base_type_t =
2343 		symbol_producer_template_t< caseless_particular_symbol_predicate_t >;
2344 
2345 public:
caseless_symbol_producer_t(char expected)2346 	caseless_symbol_producer_t( char expected )
2347 		:	base_type_t{ caseless_particular_symbol_predicate_t{expected} }
2348 	{}
2349 };
2350 
2351 //
2352 // symbol_from_range_producer_t
2353 //
2354 /*!
2355  * @brief A producer for the case when a symbol should belong
2356  * to specified range.
2357  *
2358  * Range is inclusive. It means that `(ch >= left && ch <= right)`.
2359  *
2360  * @since v.0.6.9
2361  */
2362 class symbol_from_range_producer_t
2363 	: public symbol_producer_template_t< symbol_from_range_predicate_t >
2364 {
2365 	using base_type_t =
2366 		symbol_producer_template_t< symbol_from_range_predicate_t >;
2367 
2368 public:
symbol_from_range_producer_t(char left,char right)2369 	symbol_from_range_producer_t( char left, char right )
2370 		:	base_type_t{ symbol_from_range_predicate_t{left, right} }
2371 	{}
2372 };
2373 
2374 //
2375 // digit_producer_t
2376 //
2377 /*!
2378  * @brief A producer for the case when a decimal digit is expected
2379  * in the input stream.
2380  *
2381  * In the case of success returns the extracted character.
2382  *
2383  * @since v.0.6.1
2384  */
2385 class digit_producer_t
2386 	: public symbol_producer_template_t< is_digit_predicate_t >
2387 {
2388 public:
digit_producer_t()2389 	digit_producer_t() {}
2390 };
2391 
2392 //
2393 // hexdigit_producer_t
2394 //
2395 /*!
2396  * @brief A producer for the case when a hexadecimal digit is expected
2397  * in the input stream.
2398  *
2399  * In the case of success returns the extracted character.
2400  *
2401  * @since v.0.6.6
2402  */
2403 class hexdigit_producer_t
2404 	: public symbol_producer_template_t< is_hexdigit_predicate_t >
2405 {
2406 public:
hexdigit_producer_t()2407 	hexdigit_producer_t() {}
2408 };
2409 
2410 //
2411 // try_parse_digits_with_digits_limit
2412 //
2413 /*!
2414  * @brief Helper function for parsing integers with respect to
2415  * the number of digits to be consumed.
2416  *
2417  * Usage example:
2418  * @code
2419  * // For the case of unsigned or positive signed integer:
2420  * auto r = try_parse_digits_with_digits_limit<unsigned int>(from,
2421  * 		expected_digits(4),
2422  * 		restinio::impl::overflow_controlled_integer_accumulator_t<unsigned int, 10>{});
2423  * // For the case of negative signed integer.
2424  * auto r = try_parse_digits_with_digits_limit<short>(from,
2425  * 		expected_digits(4),
2426  * 		restinio::impl::overflow_controlled_integer_accumulator_t<
2427  * 				short,
2428  * 				10,
2429  * 				restinio::impl::check_negative_extremum>{});
2430  * @endcode
2431  *
2432  * @since v.0.6.6
2433  */
2434 template< typename T, typename Value_Accumulator >
2435 RESTINIO_NODISCARD
2436 expected_t< T, parse_error_t >
try_parse_digits_with_digits_limit(source_t & from,digits_to_consume_t digits_limit,Value_Accumulator acc)2437 try_parse_digits_with_digits_limit(
2438 	source_t & from,
2439 	digits_to_consume_t digits_limit,
2440 	Value_Accumulator acc ) noexcept
2441 {
2442 	source_t::content_consumer_t consumer{ from };
2443 
2444 	digits_to_consume_t::underlying_int_t symbols_processed{};
2445 
2446 	for( auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
2447 	{
2448 		if( is_digit(ch.m_ch) )
2449 		{
2450 			acc.next_digit( static_cast<T>(ch.m_ch - '0') );
2451 
2452 			if( acc.overflow_detected() )
2453 				return make_unexpected( parse_error_t{
2454 						consumer.started_at(),
2455 						error_reason_t::illegal_value_found
2456 				} );
2457 
2458 			++symbols_processed;
2459 			if( symbols_processed == digits_limit.max() )
2460 				break;
2461 		}
2462 		else
2463 		{
2464 			from.putback();
2465 			break;
2466 		}
2467 	}
2468 
2469 	if( symbols_processed < digits_limit.min() )
2470 		// Not all required digits are extracted.
2471 		return make_unexpected( parse_error_t{
2472 				from.current_position(),
2473 				error_reason_t::pattern_not_found
2474 		} );
2475 	else
2476 	{
2477 		consumer.commit();
2478 		return acc.value();
2479 	}
2480 }
2481 
2482 //
2483 // try_parse_hexdigits_with_digits_limit
2484 //
2485 /*!
2486  * @brief Helper function for parsing integers in hexadecimal form.
2487  *
2488  * Usage example:
2489  * @code
2490  * // For the case of unsigned or positive signed integer:
2491  * auto r = try_parse_hexdigits_with_digits_limit<unsigned int>(from,
2492  * 		expected_digits(4, 8),
2493  * 		restinio::impl::overflow_controlled_integer_accumulator_t<unsigned int, 16>{});
2494  * @endcode
2495  *
2496  * @since v.0.6.6
2497  */
2498 template< typename T, typename Value_Accumulator >
2499 RESTINIO_NODISCARD
2500 expected_t< T, parse_error_t >
try_parse_hexdigits_with_digits_limit(source_t & from,digits_to_consume_t digits_limit,Value_Accumulator acc)2501 try_parse_hexdigits_with_digits_limit(
2502 	source_t & from,
2503 	digits_to_consume_t digits_limit,
2504 	Value_Accumulator acc ) noexcept
2505 {
2506 	const auto ch_to_digit = []( char ch ) -> std::pair<bool, T> {
2507 		if( ch >= '0' && ch <= '9' )
2508 			return std::make_pair( true, static_cast<T>(ch - '0') );
2509 		else if( ch >= 'A' && ch <= 'F' )
2510 			return std::make_pair( true, static_cast<T>(10 + (ch - 'A')) );
2511 		else if( ch >= 'a' && ch <= 'f' )
2512 			return std::make_pair( true, static_cast<T>(10 + (ch - 'a')) );
2513 		else
2514 			return std::make_pair( false, static_cast<T>(0) );
2515 	};
2516 
2517 	source_t::content_consumer_t consumer{ from };
2518 
2519 	digits_to_consume_t::underlying_int_t symbols_processed{};
2520 
2521 	for( auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
2522 	{
2523 		const auto d = ch_to_digit( ch.m_ch );
2524 		if( d.first )
2525 		{
2526 			acc.next_digit( d.second );
2527 
2528 			if( acc.overflow_detected() )
2529 				return make_unexpected( parse_error_t{
2530 						consumer.started_at(),
2531 						error_reason_t::illegal_value_found
2532 				} );
2533 
2534 			++symbols_processed;
2535 			if( symbols_processed == digits_limit.max() )
2536 				break;
2537 		}
2538 		else
2539 		{
2540 			from.putback();
2541 			break;
2542 		}
2543 	}
2544 
2545 	if( symbols_processed < digits_limit.min() )
2546 		// Not all required digits are extracted.
2547 		return make_unexpected( parse_error_t{
2548 				from.current_position(),
2549 				error_reason_t::pattern_not_found
2550 		} );
2551 	else
2552 	{
2553 		consumer.commit();
2554 		return acc.value();
2555 	}
2556 }
2557 
2558 //
2559 // non_negative_decimal_number_producer_t
2560 //
2561 /*!
2562  * @brief A producer for the case when a non-negative decimal number is
2563  * expected in the input stream.
2564  *
2565  * In the case of success returns the extracted number.
2566  *
2567  * @since v.0.6.2
2568  */
2569 template< typename T >
2570 class non_negative_decimal_number_producer_t : public producer_tag< T >
2571 {
2572 public:
2573 	RESTINIO_NODISCARD
2574 	expected_t< T, parse_error_t >
try_parse(source_t & from) const2575 	try_parse( source_t & from ) const noexcept
2576 	{
2577 		return try_parse_digits_with_digits_limit< T >(
2578 				from,
2579 				digits_to_consume_t::from_one_to_max(),
2580 				restinio::impl::overflow_controlled_integer_accumulator_t<T, 10>{} );
2581 	}
2582 };
2583 
2584 //
2585 // non_negative_decimal_number_producer_with_digits_limit_t
2586 //
2587 /*!
2588  * @brief A producer for the case when a non-negative decimal number is
2589  * expected in the input stream.
2590  *
2591  * This class takes into account a number of digits to be consumed.
2592  *
2593  * In the case of success returns the extracted number.
2594  *
2595  * @since v.0.6.6
2596  */
2597 template< typename T >
2598 class non_negative_decimal_number_producer_with_digits_limit_t
2599 	:	public non_negative_decimal_number_producer_t<T>
2600 {
2601 	digits_to_consume_t m_digits_limit;
2602 
2603 public:
non_negative_decimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)2604 	non_negative_decimal_number_producer_with_digits_limit_t(
2605 		digits_to_consume_t digits_limit )
2606 		:	m_digits_limit{ digits_limit }
2607 	{}
2608 
2609 	RESTINIO_NODISCARD
2610 	expected_t< T, parse_error_t >
try_parse(source_t & from) const2611 	try_parse( source_t & from ) const noexcept
2612 	{
2613 		return try_parse_digits_with_digits_limit< T >(
2614 				from,
2615 				m_digits_limit,
2616 				restinio::impl::overflow_controlled_integer_accumulator_t<T, 10>{} );
2617 	}
2618 };
2619 
2620 //
2621 // hexadecimal_number_producer_t
2622 //
2623 /*!
2624  * @brief A producer for the case when a number in hexadecimal form is expected
2625  * in the input stream.
2626  *
2627  * In the case of success returns the extracted number.
2628  *
2629  * @since v.0.6.6
2630  */
2631 template< typename T >
2632 class hexadecimal_number_producer_t : public producer_tag< T >
2633 {
2634 	static_assert( std::is_unsigned<T>::value,
2635 			"T is expected to be unsigned type" );
2636 
2637 public:
2638 	RESTINIO_NODISCARD
2639 	expected_t< T, parse_error_t >
try_parse(source_t & from) const2640 	try_parse( source_t & from ) const noexcept
2641 	{
2642 		return try_parse_hexdigits_with_digits_limit< T >(
2643 				from,
2644 				digits_to_consume_t::from_one_to_max(),
2645 				restinio::impl::overflow_controlled_integer_accumulator_t<T, 16>{} );
2646 	}
2647 };
2648 
2649 //
2650 // hexadecimal_number_producer_with_digits_limit_t
2651 //
2652 /*!
2653  * @brief A producer for the case when a number in hexadecimal form is expected
2654  * in the input stream.
2655  *
2656  * This class takes into account a number of digits to be consumed.
2657  *
2658  * In the case of success returns the extracted number.
2659  *
2660  * @since v.0.6.6
2661  */
2662 template< typename T >
2663 class hexadecimal_number_producer_with_digits_limit_t
2664 	:	public hexadecimal_number_producer_t< T >
2665 {
2666 	digits_to_consume_t m_digits_limit;
2667 
2668 public:
hexadecimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)2669 	hexadecimal_number_producer_with_digits_limit_t(
2670 		digits_to_consume_t digits_limit )
2671 		:	m_digits_limit{ digits_limit }
2672 	{}
2673 
2674 	RESTINIO_NODISCARD
2675 	expected_t< T, parse_error_t >
try_parse(source_t & from) const2676 	try_parse( source_t & from ) const noexcept
2677 	{
2678 		return try_parse_hexdigits_with_digits_limit< T >(
2679 				from,
2680 				m_digits_limit,
2681 				restinio::impl::overflow_controlled_integer_accumulator_t<T, 16>{} );
2682 	}
2683 };
2684 
2685 //
2686 // decimal_number_producer_t
2687 //
2688 /*!
2689  * @brief A producer for the case when a signed decimal number is
2690  * expected in the input stream.
2691  *
2692  * In the case of success returns the extracted number.
2693  *
2694  * @since v.0.6.6
2695  */
2696 template< typename T >
2697 class decimal_number_producer_t : public producer_tag<T>
2698 {
2699 	static_assert( std::is_signed<T>::value,
2700 			"decimal_number_producer_t can be used only for signed types" );
2701 
2702 public:
2703 	using try_parse_result_type = expected_t< T, parse_error_t >;
2704 
2705 	RESTINIO_NODISCARD
2706 	try_parse_result_type
try_parse(source_t & from) const2707 	try_parse( source_t & from ) const noexcept
2708 	{
2709 		return try_parse_impl( from,
2710 				[]() noexcept {
2711 					return digits_to_consume_t::from_one_to_max();
2712 				} );
2713 	}
2714 
2715 protected:
2716 	template< typename Digits_Limit_Maker >
2717 	RESTINIO_NODISCARD
2718 	try_parse_result_type
try_parse_impl(source_t & from,Digits_Limit_Maker && digits_limit_maker) const2719 	try_parse_impl(
2720 		source_t & from,
2721 		Digits_Limit_Maker && digits_limit_maker ) const noexcept
2722 	{
2723 		source_t::content_consumer_t consumer{ from };
2724 
2725 		auto sign_ch = from.getch();
2726 		if( !sign_ch.m_eof )
2727 		{
2728 			const auto r = try_parse_with_this_first_symbol(
2729 					from,
2730 					sign_ch.m_ch,
2731 					std::forward<Digits_Limit_Maker>(digits_limit_maker) );
2732 
2733 			if( r )
2734 				consumer.commit();
2735 
2736 			return r;
2737 		}
2738 		else
2739 			return make_unexpected( parse_error_t{
2740 					from.current_position(),
2741 					error_reason_t::pattern_not_found
2742 			} );
2743 	}
2744 
2745 private:
2746 	template< typename Digits_Limit_Maker >
2747 	RESTINIO_NODISCARD
2748 	static try_parse_result_type
try_parse_with_this_first_symbol(source_t & from,char first_symbol,Digits_Limit_Maker && digits_limit_maker)2749 	try_parse_with_this_first_symbol(
2750 		source_t & from,
2751 		char first_symbol,
2752 		Digits_Limit_Maker && digits_limit_maker ) noexcept
2753 	{
2754 		using restinio::impl::overflow_controlled_integer_accumulator_t;
2755 		using restinio::impl::check_negative_extremum;
2756 
2757 		if( '-' == first_symbol )
2758 		{
2759 			const auto r = try_parse_digits_with_digits_limit< T >(
2760 					from,
2761 					digits_limit_maker(),
2762 					overflow_controlled_integer_accumulator_t<
2763 							T,
2764 							10,
2765 							check_negative_extremum >{} );
2766 			if( r )
2767 				return static_cast< T >( -(*r) ); // This static_cast is required
2768 					// for clang compiler that warns that if type of *r is `short`,
2769 					// then -(*r) will have type `int`.
2770 			else
2771 				return r;
2772 		}
2773 		else if( '+' == first_symbol )
2774 		{
2775 			return try_parse_digits_with_digits_limit< T >(
2776 					from,
2777 					digits_limit_maker(),
2778 					overflow_controlled_integer_accumulator_t< T, 10 >{} );
2779 		}
2780 		else if( is_digit(first_symbol) )
2781 		{
2782 			from.putback();
2783 			return try_parse_digits_with_digits_limit< T >(
2784 					from,
2785 					digits_limit_maker(),
2786 					overflow_controlled_integer_accumulator_t< T, 10 >{} );
2787 		}
2788 
2789 		return make_unexpected( parse_error_t{
2790 				from.current_position(),
2791 				error_reason_t::pattern_not_found
2792 		} );
2793 	}
2794 };
2795 
2796 //
2797 // decimal_number_producer_with_digits_limit_t
2798 //
2799 /*!
2800  * @brief A producer for the case when a signed decimal number is
2801  * expected in the input stream.
2802  *
2803  * This class takes into account a number of digits to be consumed.
2804  *
2805  * In the case of success returns the extracted number.
2806  *
2807  * @since v.0.6.6
2808  */
2809 template< typename T >
2810 class decimal_number_producer_with_digits_limit_t
2811 	:	public decimal_number_producer_t< T >
2812 {
2813 	digits_to_consume_t m_digits_limit;
2814 
2815 public:
decimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)2816 	decimal_number_producer_with_digits_limit_t(
2817 		digits_to_consume_t digits_limit )
2818 		:	m_digits_limit{ digits_limit }
2819 	{}
2820 
2821 	RESTINIO_NODISCARD
2822 	auto
try_parse(source_t & from) const2823 	try_parse( source_t & from ) const noexcept
2824 	{
2825 		return this->try_parse_impl(
2826 				from,
2827 				[this]() noexcept { return m_digits_limit; } );
2828 	}
2829 };
2830 
2831 //
2832 // any_value_skipper_t
2833 //
2834 /*!
2835  * @brief A special consumer that simply throws any value away.
2836  *
2837  * This consumer is intended to be used in the case when the presence
2838  * of some value should be checked but the value itself isn't needed.
2839  *
2840  * @since v.0.6.1
2841  */
2842 struct any_value_skipper_t : public consumer_tag
2843 {
2844 	template< typename Target_Type, typename Value >
2845 	void
consumerestinio::easy_parser::impl::any_value_skipper_t2846 	consume( Target_Type &, Value && ) const noexcept {}
2847 };
2848 
2849 //
2850 // as_result_consumer_t
2851 //
2852 /*!
2853  * @brief A consumer for the case when the current value should
2854  * be returned as the result for the producer at one level up.
2855  *
2856  * For example that consumer can be necessary for rules like that:
2857    @verbatim
2858 	T := 'v' '=' token
2859 	@endverbatim
2860  * such rule will be implemented by a such sequence of clauses:
2861  * @code
2862  * produce<std::string>(symbol('v'), symbol('='), token_p() >> as_result());
2863  * @endcode
2864  * The result of `token_p()` producer in a subclause should be returned
2865  * as the result of top-level producer.
2866  *
2867  * @since v.0.6.1
2868  */
2869 struct as_result_consumer_t : public consumer_tag
2870 {
2871 	template< typename Target_Type, typename Value >
2872 	void
consumerestinio::easy_parser::impl::as_result_consumer_t2873 	consume( Target_Type & dest, Value && src ) const
2874 	{
2875 		result_wrapper_for_t<Target_Type>::as_result(
2876 				dest, std::forward<Value>(src) );
2877 	}
2878 };
2879 
2880 //
2881 // just_result_consumer_t
2882 //
2883 /*!
2884  * @brief A consumer for the case when a specific value should
2885  * be used as the result instead of the value produced on
2886  * the previous step.
2887  *
2888  * @since v.0.6.6
2889  */
2890 template< typename Result_Type >
2891 class just_result_consumer_t : public consumer_tag
2892 {
2893 	Result_Type m_result;
2894 
2895 	// NOTE: this helper method is necessary for MSVC++ compiler.
2896 	// It's because MSVC++ can't compile expression:
2897 	//
2898 	// as_result(dest, Result_Type{m_result})
2899 	//
2900 	// in consume() method for trivial types like size_t.
2901 	Result_Type
make_copy_of_result() const2902 	make_copy_of_result() const
2903 		noexcept(noexcept(Result_Type{m_result}))
2904 	{
2905 		return m_result;
2906 	}
2907 
2908 public :
2909 	template< typename Result_Arg >
just_result_consumer_t(Result_Arg && result)2910 	just_result_consumer_t( Result_Arg && result )
2911 		noexcept(noexcept(Result_Type{std::forward<Result_Arg>(result)}))
2912 		:	m_result{ std::forward<Result_Arg>(result) }
2913 	{}
2914 
2915 	template< typename Target_Type, typename Value >
2916 	void
consume(Target_Type & dest,Value &&) const2917 	consume( Target_Type & dest, Value && ) const
2918 	{
2919 		result_wrapper_for_t<Target_Type>::as_result(
2920 				dest,
2921 				// NOTE: use a copy of m_result.
2922 				make_copy_of_result() );
2923 	}
2924 };
2925 
2926 //
2927 // custom_consumer_t
2928 //
2929 /*!
2930  * @brief A template for consumers that are released by lambda/functional
2931  * objects.
2932  *
2933  * @tparam C the type of lambda/functional object/function pointer to
2934  * be used as the actual consumer.
2935  *
2936  * @since v.0.6.1
2937  */
2938 template< typename C >
2939 class custom_consumer_t : public consumer_tag
2940 {
2941 	C m_consumer;
2942 
2943 public :
custom_consumer_t(C && consumer)2944 	custom_consumer_t( C && consumer ) : m_consumer{std::move(consumer)} {}
2945 
2946 	template< typename Target_Type, typename Value >
2947 	void
consume(Target_Type & dest,Value && src) const2948 	consume( Target_Type & dest, Value && src ) const
2949 		noexcept(noexcept(m_consumer(dest, std::forward<Value>(src))))
2950 	{
2951 		m_consumer( dest, std::forward<Value>(src) );
2952 	}
2953 };
2954 
2955 //
2956 // field_setter_consumer_t
2957 //
2958 /*!
2959  * @brief A template for consumers that store a value to the specified
2960  * field of a target object.
2961  *
2962  * @tparam F type of the target field
2963  * @tparam C type of the target object.
2964  *
2965  * @since v.0.6.1
2966  */
2967 template< typename F, typename C >
2968 class field_setter_consumer_t : public consumer_tag
2969 {
2970 	using pointer_t = F C::*;
2971 
2972 	pointer_t m_ptr;
2973 
2974 public :
field_setter_consumer_t(pointer_t ptr)2975 	field_setter_consumer_t( pointer_t ptr ) noexcept : m_ptr{ptr} {}
2976 
2977 	// NOTE: it seems that this method won't be compiled if
2978 	// result_value_wrapper::result_type differs from
2979 	// result_value_wrapper::wrapped_type.
2980 	//
2981 	// This is not a problem for the current version.
2982 	// But this moment would require more attention in the future.
2983 	void
consume(C & to,F && value) const2984 	consume( C & to, F && value ) const
2985 		noexcept(noexcept(to.*m_ptr = std::move(value)))
2986 	{
2987 		to.*m_ptr = std::move(value);
2988 	}
2989 };
2990 
2991 /*!
2992  * @brief A special operator to connect a value producer with
2993  * field_setter_consumer.
2994  *
2995  * @since v.0.6.1
2996  */
2997 template< typename P, typename F, typename C >
2998 RESTINIO_NODISCARD
2999 std::enable_if_t<
3000 	is_producer_v<P>,
3001 	consume_value_clause_t< P, field_setter_consumer_t<F,C> > >
operator >>(P producer,F C::* member_ptr)3002 operator>>( P producer, F C::*member_ptr )
3003 {
3004 	return {
3005 			std::move(producer),
3006 			field_setter_consumer_t<F,C>{ member_ptr }
3007 	};
3008 }
3009 
3010 //
3011 // tuple_item_consumer_t
3012 //
3013 /*!
3014  * @brief A consumer that stores a result value at the specified
3015  * index in the result tuple.
3016  *
3017  * @since v.0.6.6
3018  */
3019 template< std::size_t Index >
3020 struct tuple_item_consumer_t : public consumer_tag
3021 {
3022 	// NOTE: it seems that this method won't be compiled if
3023 	// result_value_wrapper::result_type differs from
3024 	// result_value_wrapper::wrapped_type.
3025 	//
3026 	// This is not a problem for the current version.
3027 	// But this moment would require more attention in the future.
3028 	template< typename Target_Type, typename Value >
3029 	void
consumerestinio::easy_parser::impl::tuple_item_consumer_t3030 	consume( Target_Type && to, Value && value )
3031 	{
3032 		std::get<Index>(std::forward<Target_Type>(to)) =
3033 				std::forward<Value>(value);
3034 	}
3035 };
3036 
3037 //
3038 // to_lower_transformer_t
3039 //
3040 template< typename Input_Type >
3041 struct to_lower_transformer_t;
3042 
3043 /*!
3044  * @brief An implementation of transformer that converts the content
3045  * of the input std::string to lower case.
3046  *
3047  * @since v.0.6.1
3048  */
3049 template<>
3050 struct to_lower_transformer_t< std::string >
3051 	: public transformer_tag< std::string >
3052 {
3053 	using input_type = std::string;
3054 
3055 	RESTINIO_NODISCARD
3056 	result_type
transformrestinio::easy_parser::impl::to_lower_transformer_t3057 	transform( input_type && input ) const noexcept
3058 	{
3059 		result_type result{ std::move(input) };
3060 		std::transform( result.begin(), result.end(), result.begin(),
3061 			[]( unsigned char ch ) -> char {
3062 				return restinio::impl::to_lower_case(ch);
3063 			} );
3064 
3065 		return result;
3066 	}
3067 };
3068 
3069 /*!
3070  * @brief An implementation of transformer that converts the content
3071  * of the input character to lower case.
3072  *
3073  * @since v.0.6.6
3074  */
3075 template<>
3076 struct to_lower_transformer_t< char >
3077 	: public transformer_tag< char >
3078 {
3079 	using input_type = char;
3080 
3081 	RESTINIO_NODISCARD
3082 	result_type
transformrestinio::easy_parser::impl::to_lower_transformer_t3083 	transform( input_type && input ) const noexcept
3084 	{
3085 		return restinio::impl::to_lower_case(input);
3086 	}
3087 };
3088 
3089 /*!
3090  * @brief An implementation of transformer that converts the content
3091  * of the input std::array to lower case.
3092  *
3093  * @since v.0.6.6
3094  */
3095 template< std::size_t S >
3096 struct to_lower_transformer_t< std::array< char, S > >
3097 	: public transformer_tag< std::array< char, S > >
3098 {
3099 	using input_type = std::array< char, S >;
3100 	using base_type = transformer_tag< input_type >;
3101 
3102 	RESTINIO_NODISCARD
3103 	typename base_type::result_type
transformrestinio::easy_parser::impl::to_lower_transformer_t3104 	transform( input_type && input ) const noexcept
3105 	{
3106 		typename base_type::result_type result;
3107 		std::transform( input.begin(), input.end(), result.begin(),
3108 			[]( unsigned char ch ) -> char {
3109 				return restinio::impl::to_lower_case(ch);
3110 			} );
3111 
3112 		return result;
3113 	}
3114 };
3115 
3116 //
3117 // to_lower_transformer_proxy_t
3118 //
3119 /*!
3120  * @brief A proxy for the creation of an appropriate to_lower_transformer.
3121  *
3122  * @since v.0.6.6
3123  */
3124 struct to_lower_transformer_proxy_t : public transformer_proxy_tag
3125 {
3126 	template< typename Input_Type >
3127 	RESTINIO_NODISCARD
3128 	auto
make_transformerrestinio::easy_parser::impl::to_lower_transformer_proxy_t3129 	make_transformer() const noexcept
3130 	{
3131 		return to_lower_transformer_t< Input_Type >{};
3132 	}
3133 };
3134 
3135 //
3136 // just_value_transformer_t
3137 //
3138 /*!
3139  * @brief A transformer that skips incoming value and returns
3140  * a value specified by a user.
3141  *
3142  * @since v.0.6.6
3143  */
3144 template< typename T >
3145 class just_value_transformer_t : public transformer_tag< T >
3146 {
3147 	T m_value;
3148 
3149 public :
just_value_transformer_t(T v)3150 	just_value_transformer_t( T v ) noexcept(noexcept(T{std::move(v)}))
3151 		: m_value{ std::move(v) }
3152 	{}
3153 
3154 	template< typename Input >
3155 	RESTINIO_NODISCARD
3156 	T
transform(Input &&) const3157 	transform( Input && ) const noexcept(noexcept(T{m_value}))
3158 	{
3159 		return m_value;
3160 	}
3161 };
3162 
3163 //
3164 // convert_transformer_t
3165 //
3166 /*!
3167  * @brief A transformator that uses a user supplied function/functor
3168  * for conversion a value from one type to another.
3169  *
3170  * @since v.0.6.6
3171  */
3172 template< typename Output_Type, typename Converter >
3173 class convert_transformer_t : public transformer_tag< Output_Type >
3174 {
3175 	Converter m_converter;
3176 
3177 public :
3178 	template< typename Convert_Arg >
convert_transformer_t(Convert_Arg && converter)3179 	convert_transformer_t( Convert_Arg && converter )
3180 		noexcept(noexcept(Converter{std::forward<Convert_Arg>(converter)}))
3181 		: m_converter{ std::forward<Convert_Arg>(converter) }
3182 	{}
3183 
3184 	/*!
3185 	 * @brief Performs the transformation by calling the converter.
3186 	 *
3187 	 * @note
3188 	 * Since v.0.6.11 the result type changed from Output_Type to `auto`.
3189 	 * That allows to use converters that returns
3190 	 * expected_t<Output_Type, error_reason_t>.
3191 	 */
3192 	template< typename Input >
3193 	RESTINIO_NODISCARD
3194 	auto
transform(Input && input) const3195 	transform( Input && input ) const
3196 		noexcept(noexcept(m_converter(std::forward<Input>(input))))
3197 	{
3198 		using actual_result_t = std::decay_t< decltype(
3199 				m_converter(std::forward<Input>(input))
3200 			) >;
3201 
3202 		static_assert(
3203 				is_appropriate_transformer_result_type<actual_result_t>::value,
3204 				"the return value of converter should be either Output_Type or "
3205 				"expected_t<Output_Type, error_reason_t>" );
3206 
3207 		return m_converter(std::forward<Input>(input));
3208 	}
3209 };
3210 
3211 //
3212 // conversion_result_type_detector
3213 //
3214 /*!
3215  * @brief A helper template for the detection of type to be produced
3216  * as conversion procedure.
3217  *
3218  * A conversion procedure can produce either T or expected_t<T, error_reason_t>.
3219  * In the case of expected_t<T, error_reason_t> it is necessary to know T.
3220  * This helper template allows to detect T in both cases.
3221  *
3222  * @since v.0.6.11
3223  */
3224 template< typename Result_Type >
3225 struct conversion_result_type_detector
3226 {
3227 	using type = Result_Type;
3228 };
3229 
3230 template< typename Result_Type >
3231 struct conversion_result_type_detector< expected_t< Result_Type, error_reason_t > >
3232 {
3233 	using type = Result_Type;
3234 };
3235 
3236 /*!
3237  * A helper for simplification of usage of conversion_result_type_detector<R>.
3238  *
3239  * @since v.0.6.11
3240  */
3241 template< typename Result_Type >
3242 using conversion_result_type_detector_t =
3243 		typename conversion_result_type_detector<Result_Type>::type;
3244 
3245 //
3246 // convert_transformer_proxy_t
3247 //
3248 /*!
3249  * @brief A proxy for the creation of convert_transformer instances
3250  * for a specific value producers.
3251  *
3252  * @note
3253  * This class is intended to be used in implementation of operator>>
3254  * for cases like that:
3255  * @code
3256  * symbol_p('k') >> convert([](auto ch) { return 1024u; })
3257  * @endcode
3258  *
3259  * @since v.0.6.6
3260  */
3261 template< typename Converter >
3262 class convert_transformer_proxy_t : public transformer_proxy_tag
3263 {
3264 	template< typename Input_Type >
3265 	using output = conversion_result_type_detector_t<
3266 				std::decay_t< decltype(
3267 						std::declval<Converter &>()(std::declval<Input_Type&&>())
3268 					) >
3269 			>;
3270 
3271 	Converter m_converter;
3272 
3273 public :
3274 	template< typename Convert_Arg >
convert_transformer_proxy_t(Convert_Arg && converter)3275 	convert_transformer_proxy_t( Convert_Arg && converter )
3276 		noexcept(noexcept(Converter{std::forward<Convert_Arg>(converter)}))
3277 		: m_converter{ std::forward<Convert_Arg>(converter) }
3278 	{}
3279 
3280 	template< typename Input_Type >
3281 	RESTINIO_NODISCARD
3282 	auto
make_transformer() const3283 	make_transformer() const &
3284 		noexcept(noexcept(Converter{m_converter}))
3285 	{
3286 		using output_t = output<Input_Type>;
3287 
3288 		return convert_transformer_t< output_t, Converter >{ m_converter };
3289 	}
3290 
3291 	template< typename Input_Type >
3292 	RESTINIO_NODISCARD
3293 	auto
make_transformer()3294 	make_transformer() &&
3295 		noexcept(noexcept(Converter{std::move(m_converter)}))
3296 	{
3297 		using output_t = output<Input_Type>;
3298 
3299 		return convert_transformer_t< output_t, Converter >{
3300 				std::move(m_converter)
3301 		};
3302 	}
3303 };
3304 
3305 //
3306 // try_parse_exact_fragment
3307 //
3308 
3309 // Requires that begin is not equal to end.
3310 template< typename It >
3311 RESTINIO_NODISCARD
3312 expected_t< bool, parse_error_t >
try_parse_exact_fragment(source_t & from,It begin,It end)3313 try_parse_exact_fragment( source_t & from, It begin, It end )
3314 {
3315 	assert( begin != end );
3316 
3317 	source_t::content_consumer_t consumer{ from };
3318 
3319 	for( auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
3320 	{
3321 		if( ch.m_ch != *begin )
3322 			return make_unexpected( parse_error_t{
3323 					consumer.started_at(),
3324 					error_reason_t::pattern_not_found
3325 				} );
3326 		if( ++begin == end )
3327 			break;
3328 	}
3329 
3330 	if( begin != end )
3331 		return make_unexpected( parse_error_t{
3332 				consumer.started_at(),
3333 				error_reason_t::unexpected_eof
3334 			} );
3335 
3336 	consumer.commit();
3337 
3338 	return true;
3339 }
3340 
3341 //
3342 // exact_fixed_size_fragment_producer_t
3343 //
3344 /*!
3345  * @brief A producer that expects a fragment in the input and
3346  * produces boolean value if that fragment is found.
3347  *
3348  * This class is indended for working with fixed-size string literals
3349  * with terminating null-symbol.
3350  *
3351  * @since v.0.6.6
3352  */
3353 template< std::size_t Size >
3354 class exact_fixed_size_fragment_producer_t
3355 	:	public producer_tag< bool >
3356 {
3357 	static_assert( 1u < Size, "Size is expected to greater that 1" );
3358 
3359 	// NOTE: there is no space for last zero-byte.
3360 	std::array< char, Size-1u > m_fragment;
3361 
3362 public:
exact_fixed_size_fragment_producer_t(const char (& f)[Size])3363 	exact_fixed_size_fragment_producer_t( const char (&f)[Size] )
3364 	{
3365 		// NOTE: last zero-byte is discarded.
3366 		std::copy( &f[ 0 ], &f[ m_fragment.size() ], m_fragment.data() );
3367 	}
3368 
3369 	RESTINIO_NODISCARD
3370 	expected_t< bool, parse_error_t >
try_parse(source_t & from)3371 	try_parse( source_t & from )
3372 	{
3373 		return try_parse_exact_fragment( from,
3374 				m_fragment.begin(), m_fragment.end() );
3375 	}
3376 };
3377 
3378 //
3379 // exact_fragment_producer_t
3380 //
3381 /*!
3382  * @brief A producer that expects a fragment in the input and
3383  * produces boolean value if that fragment is found.
3384  *
3385  * @since v.0.6.6
3386  */
3387 class exact_fragment_producer_t
3388 	:	public producer_tag< bool >
3389 {
3390 	std::string m_fragment;
3391 
3392 public:
exact_fragment_producer_t(std::string fragment)3393 	exact_fragment_producer_t( std::string fragment )
3394 		:	m_fragment{ std::move(fragment) }
3395 	{
3396 		if( m_fragment.empty() )
3397 			throw exception_t( "'fragment' value for exact_fragment_producer_t "
3398 					"can't be empty!" );
3399 	}
3400 
3401 	RESTINIO_NODISCARD
3402 	expected_t< bool, parse_error_t >
try_parse(source_t & from)3403 	try_parse( source_t & from )
3404 	{
3405 		return try_parse_exact_fragment( from,
3406 				m_fragment.begin(), m_fragment.end() );
3407 	}
3408 };
3409 
3410 //
3411 // try_parse_caseless_exact_fragment
3412 //
3413 
3414 // Requires that begin is not equal to end.
3415 // It assumes that content in [begin, end) is already in lower case.
3416 template< typename It >
3417 RESTINIO_NODISCARD
3418 expected_t< bool, parse_error_t >
try_parse_caseless_exact_fragment(source_t & from,It begin,It end)3419 try_parse_caseless_exact_fragment( source_t & from, It begin, It end )
3420 {
3421 	assert( begin != end );
3422 
3423 	source_t::content_consumer_t consumer{ from };
3424 
3425 	for( auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
3426 	{
3427 		if( restinio::impl::to_lower_case(ch.m_ch) != *begin )
3428 			return make_unexpected( parse_error_t{
3429 					consumer.started_at(),
3430 					error_reason_t::pattern_not_found
3431 				} );
3432 		if( ++begin == end )
3433 			break;
3434 	}
3435 
3436 	if( begin != end )
3437 		return make_unexpected( parse_error_t{
3438 				consumer.started_at(),
3439 				error_reason_t::unexpected_eof
3440 			} );
3441 
3442 	consumer.commit();
3443 
3444 	return true;
3445 }
3446 
3447 //
3448 // caseless_exact_fixed_size_fragment_producer_t
3449 //
3450 /*!
3451  * @brief A producer that expects a fragment in the input and
3452  * produces boolean value if that fragment is found.
3453  *
3454  * The comparison is performed in case-insensitive manner.
3455  *
3456  * This class is indended for working with fixed-size string literals
3457  * with terminating null-symbol.
3458  *
3459  * @since v.0.6.9
3460  */
3461 template< std::size_t Size >
3462 class caseless_exact_fixed_size_fragment_producer_t
3463 	:	public producer_tag< bool >
3464 {
3465 	static_assert( 1u < Size, "Size is expected to greater that 1" );
3466 
3467 	// NOTE: there is no space for last zero-byte.
3468 	std::array< char, Size-1u > m_fragment;
3469 
3470 public:
caseless_exact_fixed_size_fragment_producer_t(const char (& f)[Size])3471 	caseless_exact_fixed_size_fragment_producer_t( const char (&f)[Size] )
3472 	{
3473 		// Content should be converted to lower-case.
3474 		// NOTE: last zero-byte is discarded.
3475 		std::transform(
3476 				&f[ 0 ], &f[ m_fragment.size() ],
3477 				m_fragment.data(),
3478 				[]( const char src ) {
3479 					return restinio::impl::to_lower_case( src );
3480 				} );
3481 	}
3482 
3483 	RESTINIO_NODISCARD
3484 	expected_t< bool, parse_error_t >
try_parse(source_t & from)3485 	try_parse( source_t & from )
3486 	{
3487 		return try_parse_caseless_exact_fragment( from,
3488 				m_fragment.begin(), m_fragment.end() );
3489 	}
3490 };
3491 
3492 //
3493 // caseless_exact_fragment_producer_t
3494 //
3495 /*!
3496  * @brief A producer that expects a fragment in the input and
3497  * produces boolean value if that fragment is found.
3498  *
3499  * The comparison is performed in case-insensitive manner.
3500  *
3501  * @since v.0.6.9
3502  */
3503 class caseless_exact_fragment_producer_t
3504 	:	public producer_tag< bool >
3505 {
3506 	std::string m_fragment;
3507 
3508 public:
caseless_exact_fragment_producer_t(std::string fragment)3509 	caseless_exact_fragment_producer_t( std::string fragment )
3510 		:	m_fragment{ std::move(fragment) }
3511 	{
3512 		if( m_fragment.empty() )
3513 			throw exception_t( "'fragment' value for exact_fragment_producer_t "
3514 					"can't be empty!" );
3515 
3516 		// Content should be converted to lower-case.
3517 		for( auto & ch : m_fragment )
3518 			ch = restinio::impl::to_lower_case( ch );
3519 	}
3520 
3521 	RESTINIO_NODISCARD
3522 	expected_t< bool, parse_error_t >
try_parse(source_t & from)3523 	try_parse( source_t & from )
3524 	{
3525 		return try_parse_caseless_exact_fragment( from,
3526 				m_fragment.begin(), m_fragment.end() );
3527 	}
3528 };
3529 
3530 } /* namespace impl */
3531 
3532 //
3533 // produce
3534 //
3535 /*!
3536  * @brief A factory function to create a producer that creates an
3537  * instance of the target type by using specified clauses.
3538  *
3539  * Usage example:
3540  * @code
3541  * produce<std::string>(symbol('v'), symbol('='), token_p() >> as_result());
3542  * @endcode
3543  *
3544  * @tparam Target_Type the type of value to be produced.
3545  * @tparam Clauses the list of clauses to be used for a new value.
3546  *
3547  * @since v.0.6.1
3548  */
3549 template<
3550 	typename Target_Type,
3551 	typename... Clauses >
3552 RESTINIO_NODISCARD
3553 auto
produce(Clauses &&...clauses)3554 produce( Clauses &&... clauses )
3555 {
3556 	static_assert( 0 != sizeof...(clauses),
3557 			"list of clauses can't be empty" );
3558 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3559 			"all arguments for produce() should be clauses" );
3560 
3561 	using producer_type_t = impl::produce_t<
3562 			Target_Type,
3563 			impl::tuple_of_entities_t<Clauses...> >;
3564 
3565 	return producer_type_t{
3566 			std::make_tuple(std::forward<Clauses>(clauses)...)
3567 	};
3568 }
3569 
3570 //
3571 // alternatives
3572 //
3573 /*!
3574  * @brief A factory function to create an alternatives clause.
3575  *
3576  * Usage example:
3577  * @code
3578  * produce<std::string>(
3579  * 	alternatives(
3580  * 		sequence(symbol('v'), symbol('='), token_p() >> as_result()),
3581  * 		sequence(symbol('T'), symbol('/'), token_p() >> as_result())
3582  * 	)
3583  * );
3584  * @endcode
3585  * Please note the usage of sequence() inside the call to
3586  * alternatives().
3587  *
3588  * @tparam Clauses the list of clauses to be used as alternatives.
3589  *
3590  * @since v.0.6.1
3591  */
3592 template< typename... Clauses >
3593 RESTINIO_NODISCARD
3594 auto
alternatives(Clauses &&...clauses)3595 alternatives( Clauses &&... clauses )
3596 {
3597 	static_assert( 0 != sizeof...(clauses),
3598 			"list of clauses can't be empty" );
3599 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3600 			"all arguments for alternatives() should be clauses" );
3601 
3602 	using clause_type_t = impl::alternatives_clause_t<
3603 			impl::tuple_of_entities_t< Clauses... > >;
3604 
3605 	return clause_type_t{
3606 			std::make_tuple(std::forward<Clauses>(clauses)...)
3607 	};
3608 }
3609 
3610 //
3611 // maybe
3612 //
3613 /*!
3614  * @brief A factory function to create an optional clause.
3615  *
3616  * Usage example:
3617  * @code
3618  * produce<std::pair<std::string, std::string>>(
3619  * 	token_p() >> &std::pair<std::string, std::string>::first,
3620  * 	maybe(
3621  * 		symbol('='),
3622  * 		token_p() >> &std::pair<std::string, std::string>::second
3623  * 	)
3624  * );
3625  * @endcode
3626  *
3627  * @tparam Clauses the list of clauses to be used as optional sequence.
3628  *
3629  * @since v.0.6.1
3630  */
3631 template< typename... Clauses >
3632 RESTINIO_NODISCARD
3633 auto
maybe(Clauses &&...clauses)3634 maybe( Clauses &&... clauses )
3635 {
3636 	static_assert( 0 != sizeof...(clauses),
3637 			"list of clauses can't be empty" );
3638 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3639 			"all arguments for maybe() should be clauses" );
3640 
3641 	using clause_type_t = impl::maybe_clause_t<
3642 			impl::tuple_of_entities_t<Clauses...> >;
3643 
3644 	return clause_type_t{
3645 			std::make_tuple(std::forward<Clauses>(clauses)...)
3646 	};
3647 }
3648 
3649 //
3650 // not_clause
3651 //
3652 /*!
3653  * @brief A factory function to create a not_clause.
3654  *
3655  * Usage example:
3656  * @code
3657  * produce<std::pair<std::string, std::string>>(
3658  * 	token_p() >> &std::pair<std::string, std::string>::first,
3659  * 	symbol(' '),
3660  * 	token_p() >> &std::pair<std::string, std::string>::second
3661  * 	not_clause(symbol('.'))
3662  * );
3663  * @endcode
3664  * this expression corresponds the following rule:
3665    @verbatim
3666    T := token SP token !'.'
3667 	@endverbatim
3668  *
3669  * @tparam Clauses the list of clauses to be used as sequence to be checked.
3670  *
3671  * @since v.0.6.1
3672  */
3673 template< typename... Clauses >
3674 RESTINIO_NODISCARD
3675 auto
not_clause(Clauses &&...clauses)3676 not_clause( Clauses &&... clauses )
3677 {
3678 	static_assert( 0 != sizeof...(clauses),
3679 			"list of clauses can't be empty" );
3680 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3681 			"all arguments for not_clause() should be clauses" );
3682 
3683 	using clause_type_t = impl::not_clause_t<
3684 			impl::tuple_of_entities_t<Clauses...> >;
3685 
3686 	return clause_type_t{
3687 			std::make_tuple(std::forward<Clauses>(clauses)...)
3688 	};
3689 }
3690 
3691 //
3692 // and_clause
3693 //
3694 /*!
3695  * @brief A factory function to create an and_clause.
3696  *
3697  * Usage example:
3698  * @code
3699  * produce<std::pair<std::string, std::string>>(
3700  * 	token_p() >> &std::pair<std::string, std::string>::first,
3701  * 	symbol(' '),
3702  * 	token_p() >> &std::pair<std::string, std::string>::second
3703  * 	and_clause(symbol(','), maybe(symbol(' ')), token_p() >> skip())
3704  * );
3705  * @endcode
3706  * this expression corresponds the following rule:
3707    @verbatim
3708    T := token SP token &(',' [' '] token)
3709 	@endverbatim
3710  *
3711  * @tparam Clauses the list of clauses to be used as sequence to be checked.
3712  *
3713  * @since v.0.6.1
3714  */
3715 template< typename... Clauses >
3716 RESTINIO_NODISCARD
3717 auto
and_clause(Clauses &&...clauses)3718 and_clause( Clauses &&... clauses )
3719 {
3720 	static_assert( 0 != sizeof...(clauses),
3721 			"list of clauses can't be empty" );
3722 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3723 			"all arguments for sequence() should be clauses" );
3724 
3725 	using clause_type_t = impl::and_clause_t<
3726 			impl::tuple_of_entities_t<Clauses...> >;
3727 
3728 	return clause_type_t{
3729 			std::make_tuple(std::forward<Clauses>(clauses)...)
3730 	};
3731 }
3732 
3733 //
3734 // sequence
3735 //
3736 /*!
3737  * @brief A factory function to create a sequence of subclauses
3738  *
3739  * Usage example:
3740  * @code
3741  * produce<std::string>(
3742  * 	alternatives(
3743  * 		sequence(symbol('v'), symbol('='), token_p() >> as_result()),
3744  * 		sequence(symbol('T'), symbol('/'), token_p() >> as_result())
3745  * 	)
3746  * );
3747  * @endcode
3748  * Please note the usage of sequence() inside the call to
3749  * alternatives().
3750  *
3751  * @tparam Clauses the list of clauses to be used as the sequence.
3752  *
3753  * @since v.0.6.1
3754  */
3755 template< typename... Clauses >
3756 RESTINIO_NODISCARD
3757 auto
sequence(Clauses &&...clauses)3758 sequence( Clauses &&... clauses )
3759 {
3760 	static_assert( 0 != sizeof...(clauses),
3761 			"list of clauses can't be empty" );
3762 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3763 			"all arguments for sequence() should be clauses" );
3764 
3765 	using clause_type_t = impl::sequence_clause_t<
3766 			impl::tuple_of_entities_t< Clauses... > >;
3767 
3768 	return clause_type_t{
3769 			std::make_tuple(std::forward<Clauses>(clauses)...)
3770 	};
3771 }
3772 
3773 //
3774 // force_only_this_alternative
3775 //
3776 /*!
3777  * @brief An alternative that should be parsed correctly or the parsing
3778  * of the whole alternatives clause should fail.
3779  *
3780  * This special clause is intended to be used to avoid mistakes in
3781  * grammars like that:
3782 @verbatim
3783 v = "key" '=' token
3784   | token '=' 1*VCHAR
3785 @endverbatim
3786  * If that grammar will be used for parsing a sentence like "key=123" then
3787  * the second alternative will be selected. It's because the parsing
3788  * of rule <tt>"key" '=' token</tt> fails at `123` and the second alternative
3789  * will be tried. And "key" will be recognized as a token.
3790  *
3791  * Before v.0.6.7 this mistake can be avoided by using rules like those:
3792 @verbatim
3793 v = "key" '=' token
3794   | !"key" token '=' 1*VCHAR
3795 @endverbatim
3796  *
3797  * Since v.0.6.7 this mistake can be avoided by using
3798  * force_only_this_alternative() function:
3799  * @code
3800  * alternatives(
3801  * 	sequence(
3802  * 		exact("key"),
3803  * 		force_only_this_alternative(
3804  * 			symbol('='),
3805  * 			token() >> skip()
3806  * 		)
3807  * 	),
3808  * 	sequence(
3809  * 		token() >> skip(),
3810  * 		symbol('='),
3811  * 		repeat(1, N, vchar_symbol_p() >> skip())
3812  * 	)
3813  * );
3814  * @endcode
3815  *
3816  * @since v.0.6.7
3817  */
3818 template< typename... Clauses >
3819 RESTINIO_NODISCARD
3820 auto
force_only_this_alternative(Clauses &&...clauses)3821 force_only_this_alternative( Clauses &&... clauses )
3822 {
3823 	static_assert( 0 != sizeof...(clauses),
3824 			"list of clauses can't be empty" );
3825 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3826 			"all arguments for force_only_this_alternative() should "
3827 			"be clauses" );
3828 
3829 	using clause_type_t = impl::forced_alternative_clause_t<
3830 			impl::tuple_of_entities_t< Clauses... > >;
3831 
3832 	return clause_type_t{
3833 			std::make_tuple(std::forward<Clauses>(clauses)...)
3834 	};
3835 }
3836 
3837 //
3838 // repeat
3839 //
3840 /*!
3841  * @brief A factory function to create repetitor of subclauses.
3842  *
3843  * Usage example:
3844  * @code
3845  * using str_pair = std::pair<std::string, std::string>;
3846  * produce<std::vector<str_pair>>(
3847  * 	produce<str_pair>(
3848  * 		token_p() >> &str_pair::first,
3849  * 		symbol('='),
3850  * 		token_p() >> &str_pair::second
3851  * 	) >> to_container(),
3852  * 	repeat(0, N,
3853  * 		symbol(','),
3854  * 		produce<str_pair>(
3855  * 			token_p() >> &str_pair::first,
3856  * 			symbol('='),
3857  * 			token_p() >> &str_pair::second
3858  * 		) >> to_container()
3859  * 	)
3860  * );
3861  * @endcode
3862  * this expression corresponds to the following rule:
3863    @verbatim
3864 	T := token '=' token *(',' token '=' token)
3865    @endverbatim
3866  *
3867  * @tparam Clauses the list of clauses to be used as the sequence
3868  * to be repeated.
3869  *
3870  * @since v.0.6.1
3871  */
3872 template<
3873 	typename... Clauses >
3874 RESTINIO_NODISCARD
3875 auto
repeat(std::size_t min_occurences,std::size_t max_occurences,Clauses &&...clauses)3876 repeat(
3877 	//! Minimal occurences of the sequences in the repetition.
3878 	std::size_t min_occurences,
3879 	//! Maximal occurences of the sequences in the repetition.
3880 	/*!
3881 	 * @note
3882 	 * The repetition will be stopped when that numer of repetitions
3883 	 * will be reached.
3884 	 */
3885 	std::size_t max_occurences,
3886 	//! The sequence of clauses to be repeated.
3887 	Clauses &&... clauses )
3888 {
3889 	static_assert( 0 != sizeof...(clauses),
3890 			"list of clauses can't be empty" );
3891 	static_assert( meta::all_of_v< impl::is_clause, Clauses... >,
3892 			"all arguments for repeat() should be clauses" );
3893 
3894 	using producer_type_t = impl::repeat_clause_t<
3895 			impl::tuple_of_entities_t<Clauses...> >;
3896 
3897 	return producer_type_t{
3898 			min_occurences,
3899 			max_occurences,
3900 			std::make_tuple(std::forward<Clauses>(clauses)...)
3901 	};
3902 }
3903 
3904 //
3905 // skip
3906 //
3907 /*!
3908  * @brief A factory function to create a skip_consumer.
3909  *
3910  * Usage example:
3911  * @code
3912  * produce<std::string>(
3913  * 	token_p() >> as_result(),
3914  * 	not_clause(symbol('='), token_p() >> skip())
3915  * );
3916  * @endcode
3917  *
3918  * @since v.0.6.1
3919  */
3920 RESTINIO_NODISCARD
3921 inline auto
skip()3922 skip() noexcept { return impl::any_value_skipper_t{}; }
3923 
3924 //
3925 // any_symbol_p
3926 //
3927 /*!
3928  * @brief A factory function to create an any_symbol_producer.
3929  *
3930  * @return a producer that expects any symbol in the input stream
3931  * and returns it.
3932  *
3933  * @since v.0.6.6
3934  */
3935 RESTINIO_NODISCARD
3936 inline auto
any_symbol_p()3937 any_symbol_p() noexcept
3938 {
3939 	return impl::symbol_producer_template_t<impl::any_symbol_predicate_t>{};
3940 }
3941 
3942 //
3943 // symbol_p
3944 //
3945 /*!
3946  * @brief A factory function to create a symbol_producer.
3947  *
3948  * @return a producer that expects @a expected in the input stream
3949  * and returns it if that character is found.
3950  *
3951  * @since v.0.6.1
3952  */
3953 RESTINIO_NODISCARD
3954 inline auto
symbol_p(char expected)3955 symbol_p( char expected ) noexcept
3956 {
3957 	return impl::symbol_producer_t{expected};
3958 }
3959 
3960 //
3961 // any_symbol_if_not_p
3962 //
3963 /*!
3964  * @brief A factory function to create a any_symbol_if_not_producer.
3965  *
3966  * @return a producer that expects any character except @a sentinel in the
3967  * input stream and returns it if that character is found.
3968  *
3969  * @since v.0.6.6
3970  */
3971 RESTINIO_NODISCARD
3972 inline auto
any_symbol_if_not_p(char sentinel)3973 any_symbol_if_not_p( char sentinel ) noexcept
3974 {
3975 	return impl::any_symbol_if_not_producer_t{sentinel};
3976 }
3977 
3978 //
3979 // caseless_symbol_p
3980 //
3981 /*!
3982  * @brief A factory function to create a caseless_symbol_producer.
3983  *
3984  * This producer performs caseless comparison of characters.
3985  *
3986  * @return a producer that expects @a expected in the input stream
3987  * and returns it if that character is found.
3988  *
3989  * @since v.0.6.6
3990  */
3991 RESTINIO_NODISCARD
3992 inline auto
caseless_symbol_p(char expected)3993 caseless_symbol_p( char expected ) noexcept
3994 {
3995 	return impl::caseless_symbol_producer_t{expected};
3996 }
3997 
3998 //
3999 // symbol_from_range_p
4000 //
4001 /*!
4002  * @brief A factory function to create a symbol_from_range_producer.
4003  *
4004  * @return a producer that expects a symbol from `[left, right]` range in the
4005  * input stream and returns it if that character is found.
4006  *
4007  * @since v.0.6.9
4008  */
4009 RESTINIO_NODISCARD
4010 inline auto
symbol_from_range_p(char left,char right)4011 symbol_from_range_p( char left, char right ) noexcept
4012 {
4013 	return impl::symbol_from_range_producer_t{left, right};
4014 }
4015 
4016 //
4017 // symbol
4018 //
4019 /*!
4020  * @brief A factory function to create a clause that expects the
4021  * speficied symbol, extracts it and then skips it.
4022  *
4023  * The call to `symbol('a')` function is an equivalent of:
4024  * @code
4025  * symbol_p('a') >> skip()
4026  * @endcode
4027  *
4028  * @since v.0.6.1
4029  */
4030 RESTINIO_NODISCARD
4031 inline auto
symbol(char expected)4032 symbol( char expected ) noexcept
4033 {
4034 	return symbol_p(expected) >> skip();
4035 }
4036 
4037 //
4038 // caseless_symbol
4039 //
4040 /*!
4041  * @brief A factory function to create a clause that expects the
4042  * speficied symbol, extracts it and then skips it.
4043  *
4044  * This clause performs caseless comparison of characters.
4045  *
4046  * The call to `caseless_symbol('a')` function is an equivalent of:
4047  * @code
4048  * caseless_symbol_p('a') >> skip()
4049  * @endcode
4050  *
4051  * @since v.0.6.6
4052  */
4053 RESTINIO_NODISCARD
4054 inline auto
caseless_symbol(char expected)4055 caseless_symbol( char expected ) noexcept
4056 {
4057 	return caseless_symbol_p(expected) >> skip();
4058 }
4059 
4060 //
4061 // symbol_from_range
4062 //
4063 /*!
4064  * @brief A factory function to create a clause that expects a symbol
4065  * from specified range, extracts it and then skips it.
4066  *
4067  * The call to `symbol_from_range('a', 'z')` function is an equivalent of:
4068  * @code
4069  * symbol_from_range_p('a', 'z') >> skip()
4070  * @endcode
4071  *
4072  * @since v.0.6.9
4073  */
4074 RESTINIO_NODISCARD
4075 inline auto
symbol_from_range(char left,char right)4076 symbol_from_range( char left, char right ) noexcept
4077 {
4078 	return symbol_from_range_p(left, right) >> skip();
4079 }
4080 
4081 //
4082 // space_p
4083 //
4084 /*!
4085  * @brief A factory function to create a space_producer.
4086  *
4087  * @return a producer that expects space character in the input stream
4088  * and returns it if that character is found.
4089  *
4090  * @since v.0.6.4
4091  */
4092 RESTINIO_NODISCARD
4093 inline auto
space_p()4094 space_p() noexcept
4095 {
4096 	return impl::symbol_producer_template_t< impl::is_space_predicate_t >{};
4097 }
4098 
4099 //
4100 // space
4101 //
4102 /*!
4103  * @brief A factory function to create a clause that expects a space,
4104  * extracts it and then skips it.
4105  *
4106  * The call to `space()` function is an equivalent of:
4107  * @code
4108  * space_p() >> skip()
4109  * @endcode
4110  *
4111  * @since v.0.6.4
4112  */
4113 RESTINIO_NODISCARD
4114 inline auto
space()4115 space() noexcept
4116 {
4117 	return space_p() >> skip();
4118 }
4119 
4120 //
4121 // digit_p
4122 //
4123 /*!
4124  * @brief A factory function to create a digit_producer.
4125  *
4126  * @return a producer that expects a decimal digit in the input stream
4127  * and returns it if a decimal digit is found.
4128  *
4129  * @since v.0.6.1
4130  */
4131 RESTINIO_NODISCARD
4132 inline auto
digit_p()4133 digit_p() noexcept
4134 {
4135 	return impl::digit_producer_t{};
4136 }
4137 
4138 //
4139 // digit
4140 //
4141 /*!
4142  * @brief A factory function to create a clause that expects a decimal digit,
4143  * extracts it and then skips it.
4144  *
4145  * The call to `digit()` function is an equivalent of:
4146  * @code
4147  * digit_p() >> skip()
4148  * @endcode
4149  *
4150  * @since v.0.6.6
4151  */
4152 RESTINIO_NODISCARD
4153 inline auto
digit()4154 digit() noexcept
4155 {
4156 	return digit_p() >> skip();
4157 }
4158 
4159 //
4160 // hexdigit_p
4161 //
4162 /*!
4163  * @brief A factory function to create a hexdigit_producer.
4164  *
4165  * @return a producer that expects a hexadecimal digit in the input stream
4166  * and returns it if a hexadecimal digit is found.
4167  *
4168  * @since v.0.6.6
4169  */
4170 RESTINIO_NODISCARD
4171 inline auto
hexdigit_p()4172 hexdigit_p() noexcept
4173 {
4174 	return impl::hexdigit_producer_t{};
4175 }
4176 
4177 //
4178 // hexdigit
4179 //
4180 /*!
4181  * @brief A factory function to create a clause that expects a hexadecimal
4182  * digit, extracts it and then skips it.
4183  *
4184  * The call to `hexdigit()` function is an equivalent of:
4185  * @code
4186  * hexdigit_p() >> skip()
4187  * @endcode
4188  *
4189  * @since v.0.6.6
4190  */
4191 RESTINIO_NODISCARD
4192 inline auto
hexdigit()4193 hexdigit() noexcept
4194 {
4195 	return hexdigit_p() >> skip();
4196 }
4197 
4198 //
4199 // non_negative_decimal_number_p
4200 //
4201 /*!
4202  * @brief A factory function to create a non_negative_decimal_number_producer.
4203  *
4204  * @note
4205  * This parser consumes all digits until the first non-digit symbol will
4206  * be found in the input. It means that in the case of `1111someword` the
4207  * first four digits (e.g. `1111`) will be extracted from the input and
4208  * the remaining part (e.g. `someword`) won't be consumed by this parser.
4209  *
4210  * @return a producer that expects a positive decimal number in the input stream
4211  * and returns it if a number is found.
4212  *
4213  * @since v.0.6.2
4214  */
4215 template< typename T >
4216 RESTINIO_NODISCARD
4217 inline auto
non_negative_decimal_number_p()4218 non_negative_decimal_number_p() noexcept
4219 {
4220 	return impl::non_negative_decimal_number_producer_t<T>{};
4221 }
4222 
4223 //
4224 // non_negative_decimal_number_p
4225 //
4226 /*!
4227  * @brief A factory function to create a non_negative_decimal_number_producer.
4228  *
4229  * @note
4230  * This parser consumes a number of digits with respect to @a digits_limit.
4231  *
4232  * Usage example:
4233  * @code
4234  * using namespace restinio::easy_parser;
4235  *
4236  * struct compound_number {
4237  * 	short prefix_;
4238  * 	int suffix_;
4239  * };
4240  *
4241  * auto parse = produce<compound_number>(
4242  * 	non_negative_decimal_number_p<short>(expected_digits(2, 5))
4243  * 		>> &compound_number::prefix_,
4244  * 	non_negative_decimal_number_p<int>(expected_digits(7, 12))
4245  * 		>> &compound_number::suffix_
4246  * );
4247  * @endcode
4248  *
4249  * @return a producer that expects a positive decimal number in the input stream
4250  * and returns it if a number is found.
4251  *
4252  * @since v.0.6.2
4253  */
4254 template< typename T >
4255 RESTINIO_NODISCARD
4256 inline auto
non_negative_decimal_number_p(digits_to_consume_t digits_limit)4257 non_negative_decimal_number_p( digits_to_consume_t digits_limit ) noexcept
4258 {
4259 	return impl::non_negative_decimal_number_producer_with_digits_limit_t<T>{
4260 			digits_limit
4261 	};
4262 }
4263 
4264 //FIXME: remove in v.0.7.0!
4265 //
4266 // positive_decimal_number_p
4267 //
4268 /*!
4269  * @brief A factory function to create a producer for non-negative
4270  * decimal numbers.
4271  *
4272  * @deprecated Use non_negative_decimal_number_p.
4273  *
4274  * @since v.0.6.2
4275  */
4276 template< typename T >
4277 [[deprecated]] RESTINIO_NODISCARD
4278 inline auto
positive_decimal_number_producer()4279 positive_decimal_number_producer() noexcept
4280 {
4281 	return non_negative_decimal_number_p<T>();
4282 }
4283 
4284 //
4285 // hexadecimal_number_p
4286 //
4287 /*!
4288  * @brief A factory function to create a hexadecimal_number_producer.
4289  *
4290  * @note
4291  * This parser consumes all digits until the first non-digit symbol will
4292  * be found in the input. It means that in the case of `1111someword` the
4293  * first four digits (e.g. `1111`) will be extracted from the input and
4294  * the remaining part (e.g. `someword`) won't be consumed by this parser.
4295  *
4296  * @attention
4297  * T should be an unsigned type.
4298  *
4299  * @return a producer that expects a positive hexadecimal number in the input
4300  * stream and returns it if a number is found.
4301  *
4302  * @since v.0.6.6
4303  */
4304 template< typename T >
4305 RESTINIO_NODISCARD
4306 inline auto
hexadecimal_number_p()4307 hexadecimal_number_p() noexcept
4308 {
4309 	return impl::hexadecimal_number_producer_t<T>{};
4310 }
4311 
4312 //
4313 // hexadecimal_number_p
4314 //
4315 /*!
4316  * @brief A factory function to create a hexadecimal_number_producer.
4317  *
4318  * @note
4319  * This parser consumes a number of digits with respect to @a digits_limit.
4320  *
4321  * Usage example:
4322  * @code
4323  * using namespace restinio::easy_parser;
4324  *
4325  * struct compound_number {
4326  * 	short prefix_;
4327  * 	int suffix_;
4328  * };
4329  *
4330  * auto parse = produce<compound_number>(
4331  * 	hexadecimal_number_p<short>(expected_digits(4))
4332  * 		>> &compound_number::prefix_,
4333  * 	hexadecimal_number_p<int>(expected_digits(7, 12))
4334  * 		>> &compound_number::suffix_
4335  * );
4336  * @endcode
4337  *
4338  * @attention
4339  * T should be an unsigned type.
4340  *
4341  * @return a producer that expects a positive hexadecimal number in the input
4342  * stream and returns it if a number is found.
4343  *
4344  * @since v.0.6.6
4345  */
4346 template< typename T >
4347 RESTINIO_NODISCARD
4348 inline auto
hexadecimal_number_p(digits_to_consume_t digits_limit)4349 hexadecimal_number_p( digits_to_consume_t digits_limit ) noexcept
4350 {
4351 	return impl::hexadecimal_number_producer_with_digits_limit_t<T>{
4352 			digits_limit
4353 	};
4354 }
4355 
4356 //
4357 // decimal_number_p
4358 //
4359 /*!
4360  * @brief A factory function to create a decimal_number_producer.
4361  *
4362  * Parses numbers in the form:
4363 @verbatim
4364 number := [sign] DIGIT+
4365 sign   := '-' | '+'
4366 @endverbatim
4367  *
4368  * @note
4369  * This parser consumes all digits until the first non-digit symbol will be
4370  * found in the input. It means that in the case of `-1111someword` the leading
4371  * minus sign and thefirst four digits (e.g. `-1111`) will be extracted from
4372  * the input and the remaining part (e.g. `someword`) won't be consumed by this
4373  * parser.
4374  *
4375  * @attention
4376  * Can be used only for singed number types (e.g. short, int, long,
4377  * std::int32_t and so on).
4378  *
4379  * @return a producer that expects a decimal number in the input stream
4380  * and returns it if a number is found.
4381  *
4382  * @since v.0.6.6
4383  */
4384 template< typename T >
4385 RESTINIO_NODISCARD
4386 inline auto
decimal_number_p()4387 decimal_number_p() noexcept
4388 {
4389 	static_assert( std::is_signed<T>::value,
4390 			"decimal_number_p() can be used only for signed numeric types" );
4391 
4392 	return impl::decimal_number_producer_t<T>{};
4393 }
4394 
4395 //
4396 // decimal_number_p
4397 //
4398 /*!
4399  * @brief A factory function to create a decimal_number_producer.
4400  *
4401  * Parses numbers in the form:
4402 @verbatim
4403 number := [sign] DIGIT+
4404 sign   := '-' | '+'
4405 @endverbatim
4406  *
4407  * @note
4408  * This parser consumes a number of digits with respect to @a digits_limit.
4409  * The leading sign (if present) is not added to a number of extracted digits.
4410  *
4411  * Usage example:
4412  * @code
4413  * using namespace restinio::easy_parser;
4414  *
4415  * struct compound_number {
4416  * 	short prefix_;
4417  * 	int suffix_;
4418  * };
4419  *
4420  * auto parse = produce<compound_number>(
4421  * 	decimal_number_p<short>(expected_digits(4))
4422  * 		>> &compound_number::prefix_,
4423  * 	decimal_number_p<int>(expected_digits(7, 12))
4424  * 		>> &compound_number::suffix_
4425  * );
4426  * @endcode
4427  *
4428  * @attention
4429  * Can be used only for singed number types (e.g. short, int, long,
4430  * std::int32_t and so on).
4431  *
4432  * @return a producer that expects a decimal number in the input stream
4433  * and returns it if a number is found.
4434  *
4435  * @since v.0.6.6
4436  */
4437 template< typename T >
4438 RESTINIO_NODISCARD
4439 inline auto
decimal_number_p(digits_to_consume_t digits_limit)4440 decimal_number_p( digits_to_consume_t digits_limit ) noexcept
4441 {
4442 	static_assert( std::is_signed<T>::value,
4443 			"decimal_number_p() can be used only for signed numeric types" );
4444 
4445 	return impl::decimal_number_producer_with_digits_limit_t<T>{
4446 			digits_limit
4447 	};
4448 }
4449 
4450 //
4451 // as_result
4452 //
4453 /*!
4454  * @brief A factory function to create a as_result_consumer.
4455  *
4456  * Usage example:
4457  * @code
4458  * produce<std::string>(
4459  * 	symbol('v'),
4460  * 	symbol('='),
4461  * 	token_p() >> as_result(),
4462  * 	symbol('.')
4463  * );
4464  * @endcode
4465  *
4466  * @since v.0.6.1
4467  */
4468 RESTINIO_NODISCARD
4469 inline auto
as_result()4470 as_result() noexcept { return impl::as_result_consumer_t{}; }
4471 
4472 //
4473 // custom_consumer
4474 //
4475 /*!
4476  * @brief A factory function to create a custom_consumer.
4477  *
4478  * Usage example:
4479  * @code
4480  * class composed_value {
4481  * 	std::string name_;
4482  * 	std::string value_;
4483  * public:
4484  * 	composed_value() = default;
4485  *
4486  * 	void set_name(std::string name) { name_ = std::move(name); }
4487  * 	void set_value(std::string value) { value_ = std::move(value); }
4488  * 	...
4489  * };
4490  * produce<composed_value>(
4491  * 	token_p() >> custom_consumer(
4492  * 		[](composed_value & to, std::string && what) {
4493  * 			to.set_name(std::move(what));
4494  * 		} ),
4495  * 	symbol('='),
4496  * 	token_p() >> custom_consumer(
4497  * 		[](composed_value & to, std::string && what) {
4498  * 			to.set_value(std::move(what));
4499  * 		} ),
4500  * 	symbol('.')
4501  * );
4502  * @endcode
4503  *
4504  * @note
4505  * A custom consumer should be a function/lambda/function objects with
4506  * the following prototype:
4507  * @code
4508  * void(Target_Type & destination, Value && value);
4509  * @endcode
4510  *
4511  * @since v.0.6.1
4512  */
4513 template< typename F >
4514 RESTINIO_NODISCARD
4515 auto
custom_consumer(F consumer)4516 custom_consumer( F consumer )
4517 {
4518 	using actual_consumer_t = impl::custom_consumer_t< F >;
4519 
4520 	return actual_consumer_t{ std::move(consumer) };
4521 }
4522 
4523 namespace impl
4524 {
4525 
4526 //
4527 // to_container_consumer_t
4528 //
4529 /*!
4530  * @brief A template for a consumer that stories values into a container.
4531  *
4532  * Instances of such consumer will be used inside repeat_clause_t.
4533  *
4534  * @tparam Container_Adaptor a class that knows how to store a value
4535  * into the target container. See result_value_wrapper for the
4536  * requirement for such type.
4537  *
4538  * @since v.0.6.1
4539  */
4540 struct to_container_consumer_t : public consumer_tag
4541 {
4542 	template< typename Container, typename Item >
4543 	void
consumerestinio::easy_parser::impl::to_container_consumer_t4544 	consume( Container & to, Item && item )
4545 	{
4546 		using container_adaptor_type = result_wrapper_for_t<Container>;
4547 		container_adaptor_type::to_container( to, std::move(item) );
4548 	}
4549 };
4550 
4551 } /* namespace impl */
4552 
4553 //
4554 // to_container
4555 //
4556 /*!
4557  * @brief A factory function to create a to_container_consumer.
4558  *
4559  * Usage example:
4560  * @code
4561  * using str_pair = std::pair<std::string, std::string>;
4562  * produce<std::vector<str_pair>>(
4563  * 	produce<str_pair>(
4564  * 		token_p() >> &str_pair::first,
4565  * 		symbol('='),
4566  * 		token_p() >> &str_pair::second
4567  * 	) >> to_container(),
4568  * 	repeat(0, N,
4569  * 		symbol(','),
4570  * 		produce<str_pair>(
4571  * 			token_p() >> &str_pair::first,
4572  * 			symbol('='),
4573  * 			token_p() >> &str_pair::second
4574  * 		) >> to_container()
4575  * 	)
4576  * );
4577  * @endcode
4578  *
4579  * @since v.0.6.1
4580  */
4581 RESTINIO_NODISCARD
4582 inline auto
to_container()4583 to_container()
4584 {
4585 	return impl::to_container_consumer_t();
4586 }
4587 
4588 //
4589 // to_lower
4590 //
4591 /*!
4592  * @brief A factory function to create a to_lower_transformer.
4593  *
4594  * Usage example:
4595  * @code
4596  * produce<std::string>(
4597  * 	symbol('T'), symbol(':'),
4598  * 	token_p() >> to_lower() >> as_result()
4599  * );
4600  * ...
4601  * // Since v.0.6.6 to_lower can also be used for a single character.
4602  * produce<char>(
4603  * 	exact("I="), any_symbol_p() >> to_lower() >> as_result() );
4604  * @endcode
4605  *
4606  * @since v.0.6.1
4607  */
4608 RESTINIO_NODISCARD
4609 inline auto
to_lower()4610 to_lower() noexcept { return impl::to_lower_transformer_proxy_t{}; }
4611 
4612 //
4613 // just
4614 //
4615 /*!
4616  * @brief A special transformer that replaces the produced value by
4617  * a value specified by a user.
4618  *
4619  * Usage example:
4620  * @code
4621  * produce<unsigned int>(
4622  * 	alternatives(
4623  * 		symbol('b') >> just(1u) >> as_result(),
4624  * 		symbol('k') >> just(1024u) >> as_result(),
4625  * 		symbol('m') >> just(1024u*1024u) >> as_result()
4626  * 	)
4627  * );
4628  * @endcode
4629  *
4630  * @since v.0.6.6
4631  */
4632 template< typename T >
4633 RESTINIO_NODISCARD
4634 auto
just(T value)4635 just( T value ) noexcept(noexcept(impl::just_value_transformer_t<T>{value}))
4636 {
4637 	return impl::just_value_transformer_t<T>{value};
4638 }
4639 
4640 //
4641 // just_result
4642 //
4643 /*!
4644  * @brief A special consumer that replaces the produced value by
4645  * a value specified by a user and sets that user-specified value
4646  * as the result.
4647  *
4648  * Usage example:
4649  * @code
4650  * produce<unsigned int>(
4651  * 	alternatives(
4652  * 		symbol('b') >> just_result(1u),
4653  * 		symbol('k') >> just_result(1024u),
4654  * 		symbol('m') >> just_result(1024u*1024u)
4655  * 	)
4656  * );
4657  * @endcode
4658  *
4659  * @since v.0.6.6
4660  */
4661 template< typename T >
4662 RESTINIO_NODISCARD
4663 auto
just_result(T value)4664 just_result( T value )
4665 	noexcept(noexcept(impl::just_result_consumer_t<T>{value}))
4666 {
4667 	return impl::just_result_consumer_t<T>{value};
4668 }
4669 
4670 //
4671 // convert
4672 //
4673 /*!
4674  * @brief A factory function to create convert_transformer.
4675  *
4676  * Usage example:
4677  * @code
4678  * // Parser for:
4679  * // size       := DIGIT+ [multiplier]
4680  * // multiplier := ('b'|'B') | ('k'|'K') | ('m'|'M')
4681  * struct tmp_size { std::uint32_t c_{1u}; std::uint32_t m_{1u}; };
4682  * auto size_producer = produce<std::uint64_t>(
4683  * 	produce<tmp_size>(
4684  * 		non_negative_decimal_number_p<std::uint32_t>() >> &tmp_size::c_,
4685  * 		maybe(
4686  * 			produce<std::uint32_t>(
4687  * 				alternatives(
4688  * 					caseless_symbol_p('b') >> just_result(1u),
4689  * 					caseless_symbol_p('k') >> just_result(1024u),
4690  * 					caseless_symbol_p('m') >> just_result(1024u*1024u)
4691  * 				)
4692  * 			) >> &tmp_size::m_
4693  * 		)
4694  * 	)
4695  * 	>> convert( [](const tmp_size & ts) { return std::uint64_t{ts.c_} * ts.m_; } )
4696  * 	>> as_result()
4697  * );
4698  * @endcode
4699  *
4700  * @note
4701  * Since v.0.6.11 a conversion function can have two formats. The first one is:
4702  * @code
4703  * result_type fn(input_type source_val);
4704  * @endcode
4705  * for example:
4706  * @code
4707  * convert([](const std::string & from) -> int {...})
4708  * @endcode
4709  * in that case a conversion error can only be reported via an exception.
4710  * The second one is:
4711  * @code
4712  * expected_t<result_type, error_reason_t> fn(input_type source_val);
4713  * @endcode
4714  * for example:
4715  * @code
4716  * convert([](const std::string & from) -> expected_t<int, error_reason_t> {...})
4717  * @endcode
4718  * in that case a converion error can be reported also via returning value.
4719  * For example, let's assume that in the code snippet shown above the result
4720  * value should be greater than 0. It can be checked in the conversion
4721  * function that way:
4722  * @code
4723  * convert([](const tmp_size & ts) -> expected_t<std::uint64_t, error_reason_t> {
4724  * 	const auto r = std::uint64_t{ts.c_} * ts.m_;
4725  * 	if( r )
4726  * 		return r;
4727  * 	else
4728  * 		return make_unexpected(error_reason_t::illegal_value_found);
4729  * }
4730  * @endcode
4731  *
4732  * @since v.0.6.6
4733  */
4734 template< typename Converter >
4735 RESTINIO_NODISCARD
4736 auto
convert(Converter && converter)4737 convert( Converter && converter )
4738 {
4739 	using converter_type = std::decay_t<Converter>;
4740 
4741 	using transformer_proxy_type = impl::convert_transformer_proxy_t<
4742 			converter_type >;
4743 
4744 	return transformer_proxy_type{ std::forward<Converter>(converter) };
4745 }
4746 
4747 //
4748 // exact_p
4749 //
4750 /*!
4751  * @brief A factory function that creates an instance of
4752  * exact_fragment_producer.
4753  *
4754  * Usage example:
4755  * @code
4756  * produce<std::string>(
4757  * 	alternatives(
4758  * 		exact_p("pro") >> just_result("Professional"),
4759  * 		exact_p("con") >> just_result("Consumer")
4760  * 	)
4761  * );
4762  * @endcode
4763  *
4764  * @since v.0.6.6
4765  */
4766 RESTINIO_NODISCARD
4767 inline auto
exact_p(string_view_t fragment)4768 exact_p( string_view_t fragment )
4769 {
4770 	return impl::exact_fragment_producer_t{
4771 			std::string{ fragment.data(), fragment.size() }
4772 		};
4773 }
4774 
4775 /*!
4776  * @brief A factory function that creates an instance of
4777  * exact_fragment_producer.
4778  *
4779  * Usage example:
4780  * @code
4781  * produce<std::string>(
4782  * 	alternatives(
4783  * 		exact_p("pro") >> just_result("Professional"),
4784  * 		exact_p("con") >> just_result("Consumer")
4785  * 	)
4786  * );
4787  * @endcode
4788  *
4789  * @attention
4790  * This version is dedicated to be used with string literals.
4791  * Because of that the last byte from a literal will be ignored (it's
4792  * assumed that this byte contains zero).
4793  * But this behavior would lead to unexpected results in such cases:
4794  * @code
4795  * const char prefix[]{ 'h', 'e', 'l', 'l', 'o' };
4796  *
4797  * produce<std::string>(exact_p(prefix) >> just_result("Hi!"));
4798  * @endcode
4799  * because the last byte with value 'o' will be ignored by
4800  * exact_producer. To avoid such behavior string_view_t should be
4801  * used explicitely:
4802  * @code
4803  * produce<std::string>(exact_p(string_view_t{prefix})
4804  * 		>> just_result("Hi!"));
4805  * @endcode
4806  *
4807  * @since v.0.6.6
4808  */
4809 template< std::size_t Size >
4810 RESTINIO_NODISCARD
4811 auto
exact_p(const char (& fragment)[Size])4812 exact_p( const char (&fragment)[Size] )
4813 {
4814 	return impl::exact_fixed_size_fragment_producer_t<Size>{ fragment };
4815 }
4816 
4817 //
4818 // exact
4819 //
4820 /*!
4821  * @brief A factory function that creates an instance of
4822  * exact_fragment clause.
4823  *
4824  * Usage example:
4825  * @code
4826  * produce<std::string>(exact("version="), token() >> as_result());
4827  * @endcode
4828  *
4829  * @since v.0.6.6
4830  */
4831 RESTINIO_NODISCARD
4832 inline auto
exact(string_view_t fragment)4833 exact( string_view_t fragment )
4834 {
4835 	return impl::exact_fragment_producer_t{
4836 			std::string{ fragment.data(), fragment.size() }
4837 		} >> skip();
4838 }
4839 
4840 /*!
4841  * @brief A factory function that creates an instance of
4842  * exact_fragment clause.
4843  *
4844  * Usage example:
4845  * @code
4846  * produce<std::string>(exact("version="), token() >> as_result());
4847  * @endcode
4848  *
4849  * @attention
4850  * This version is dedicated to be used with string literals.
4851  * Because of that the last byte from a literal will be ignored (it's
4852  * assumed that this byte contains zero).
4853  * But this behavior would lead to unexpected results in such cases:
4854  * @code
4855  * const char prefix[]{ 'v', 'e', 'r', 's', 'i', 'o', 'n', '=' };
4856  *
4857  * produce<std::string>(exact(prefix), token() >> as_result());
4858  * @endcode
4859  * because the last byte with value '=' will be ignored by
4860  * exact_producer. To avoid such behavior string_view_t should be
4861  * used explicitely:
4862  * @code
4863  * produce<std::string>(exact(string_view_t{prefix}),	token() >> as_result());
4864  * @endcode
4865  *
4866  * @since v.0.6.6
4867  */
4868 template< std::size_t Size >
4869 RESTINIO_NODISCARD
4870 auto
exact(const char (& fragment)[Size])4871 exact( const char (&fragment)[Size] )
4872 {
4873 	return impl::exact_fixed_size_fragment_producer_t<Size>{ fragment } >> skip();
4874 }
4875 
4876 //
4877 // caseless_exact_p
4878 //
4879 /*!
4880  * @brief A factory function that creates an instance of
4881  * caseless_exact_fragment_producer.
4882  *
4883  * Usage example:
4884  * @code
4885  * produce<std::string>(
4886  * 	alternatives(
4887  * 		caseless_exact_p("pro") >> just_result("Professional"),
4888  * 		caseless_exact_p("con") >> just_result("Consumer")
4889  * 	)
4890  * );
4891  * @endcode
4892  *
4893  * @since v.0.6.9
4894  */
4895 RESTINIO_NODISCARD
4896 inline auto
caseless_exact_p(string_view_t fragment)4897 caseless_exact_p( string_view_t fragment )
4898 {
4899 	return impl::caseless_exact_fragment_producer_t{
4900 			std::string{ fragment.data(), fragment.size() }
4901 		};
4902 }
4903 
4904 /*!
4905  * @brief A factory function that creates an instance of
4906  * caseless_exact_fragment_producer.
4907  *
4908  * Usage example:
4909  * @code
4910  * produce<std::string>(
4911  * 	alternatives(
4912  * 		caseless_exact_p("pro") >> just_result("Professional"),
4913  * 		caseless_exact_p("con") >> just_result("Consumer")
4914  * 	)
4915  * );
4916  * @endcode
4917  *
4918  * @attention
4919  * This version is dedicated to be used with string literals.
4920  * Because of that the last byte from a literal will be ignored (it's
4921  * assumed that this byte contains zero).
4922  * But this behavior would lead to unexpected results in such cases:
4923  * @code
4924  * const char prefix[]{ 'h', 'e', 'l', 'l', 'o' };
4925  *
4926  * produce<std::string>(caseless_exact_p(prefix) >> just_result("Hi!"));
4927  * @endcode
4928  * because the last byte with value 'o' will be ignored by
4929  * exact_producer. To avoid such behavior string_view_t should be
4930  * used explicitely:
4931  * @code
4932  * produce<std::string>(caseless_exact_p(string_view_t{prefix})
4933  * 		>> just_result("Hi!"));
4934  * @endcode
4935  *
4936  * @since v.0.6.9
4937  */
4938 template< std::size_t Size >
4939 RESTINIO_NODISCARD
4940 auto
caseless_exact_p(const char (& fragment)[Size])4941 caseless_exact_p( const char (&fragment)[Size] )
4942 {
4943 	return impl::caseless_exact_fixed_size_fragment_producer_t<Size>{ fragment };
4944 }
4945 
4946 //
4947 // caseless_exact
4948 //
4949 /*!
4950  * @brief A factory function that creates an instance of
4951  * caseless_exact_fragment clause.
4952  *
4953  * Usage example:
4954  * @code
4955  * produce<std::string>(caseless_exact("version="), token() >> as_result());
4956  * @endcode
4957  *
4958  * @since v.0.6.9
4959  */
4960 RESTINIO_NODISCARD
4961 inline auto
caseless_exact(string_view_t fragment)4962 caseless_exact( string_view_t fragment )
4963 {
4964 	return impl::caseless_exact_fragment_producer_t{
4965 			std::string{ fragment.data(), fragment.size() }
4966 		} >> skip();
4967 }
4968 
4969 /*!
4970  * @brief A factory function that creates an instance of
4971  * caseless_exact_fragment clause.
4972  *
4973  * Usage example:
4974  * @code
4975  * produce<std::string>(caseless_exact("version="), token() >> as_result());
4976  * @endcode
4977  *
4978  * @attention
4979  * This version is dedicated to be used with string literals.
4980  * Because of that the last byte from a literal will be ignored (it's
4981  * assumed that this byte contains zero).
4982  * But this behavior would lead to unexpected results in such cases:
4983  * @code
4984  * const char prefix[]{ 'v', 'e', 'r', 's', 'i', 'o', 'n', '=' };
4985  *
4986  * produce<std::string>(caseless_exact(prefix), token() >> as_result());
4987  * @endcode
4988  * because the last byte with value '=' will be ignored by
4989  * exact_producer. To avoid such behavior string_view_t should be
4990  * used explicitely:
4991  * @code
4992  * produce<std::string>(caseless_exact(string_view_t{prefix}),	token() >> as_result());
4993  * @endcode
4994  *
4995  * @since v.0.6.9
4996  */
4997 template< std::size_t Size >
4998 RESTINIO_NODISCARD
4999 auto
caseless_exact(const char (& fragment)[Size])5000 caseless_exact( const char (&fragment)[Size] )
5001 {
5002 	return impl::caseless_exact_fixed_size_fragment_producer_t<Size>{ fragment } >> skip();
5003 }
5004 
5005 //
5006 // try_parse
5007 //
5008 /*!
5009  * @brief Perform the parsing of the specified content by using
5010  * specified value producer.
5011  *
5012  * @note
5013  * The whole content of @a from should be consumed. There can be
5014  * whitespace remaining in @from after the return from
5015  * Producer::try_parser. But if there will be some non-whitespace
5016  * symbol the failure will be reported.
5017  * (As a side note: since v.0.6.7 all trailing spaces are removed
5018  * from @from before the parsing starts.)
5019  *
5020  * Usage example
5021  * @code
5022  * const auto tokens = try_parse(
5023  * 	"first,Second;Third;Four",
5024  * 	produce<std::vector<std::string>>(
5025  * 		token_p() >> to_lower() >> to_container(),
5026  * 		repeat( 0, N,
5027  * 			alternatives(symbol(','), symbol(';')),
5028  * 			token_p() >> to_lower() >> to_container()
5029  * 		)
5030  * 	)
5031  * );
5032  * if(tokens)
5033  * 	for(const auto & v: *tokens)
5034  * 		std::cout << v << std::endl;
5035  * @endcode
5036  *
5037  * @since v.0.6.1
5038  */
5039 template< typename Producer >
5040 RESTINIO_NODISCARD
5041 expected_t< typename Producer::result_type, parse_error_t >
try_parse(string_view_t from,Producer producer)5042 try_parse(
5043 	string_view_t from,
5044 	Producer producer )
5045 {
5046 	static_assert( impl::is_producer_v<Producer>,
5047 			"Producer should be a value producer type" );
5048 
5049 	from = impl::remove_trailing_spaces( from );
5050 	impl::source_t source{ from };
5051 
5052 	auto result = impl::top_level_clause_t< Producer >{ std::move(producer) }
5053 			.try_process( source );
5054 
5055 	if( result )
5056 	{
5057 		// We should ensure that all content has been consumed.
5058 		const auto all_content_check =
5059 				impl::ensure_no_remaining_content( source );
5060 		if( all_content_check )
5061 			return make_unexpected( *all_content_check );
5062 	}
5063 
5064 	return result;
5065 }
5066 
5067 //
5068 // make_error_description
5069 //
5070 /*!
5071  * @brief Make textual description of error returned by try_parse function.
5072  *
5073  * @note
5074  * The format of textual description is not specified and can be changed
5075  * in some future versions without notice.
5076  *
5077  * Usage example:
5078  * @code
5079  * const char * content = "first,Second;Third;Four";
5080  * const auto tokens = try_parse(
5081  * 	content,
5082  * 	produce<std::vector<std::string>>(
5083  * 		token_p() >> to_lower() >> to_container(),
5084  * 		repeat( 0, N,
5085  * 			alternatives(symbol(','), symbol(';')),
5086  * 			token_p() >> to_lower() >> to_container()
5087  * 		)
5088  * 	)
5089  * );
5090  * if(tokens)
5091  * {
5092  * 	for(const auto & v: *tokens)
5093  * 		std::cout << v << std::endl;
5094  * }
5095  * else
5096  * 	std::cerr << make_error_description(tokens.error(), content) << std::endl;
5097  * @endcode
5098  *
5099  * @since v.0.6.1
5100  */
5101 RESTINIO_NODISCARD
5102 inline std::string
make_error_description(const parse_error_t & error,string_view_t from)5103 make_error_description(
5104 	const parse_error_t & error,
5105 	string_view_t from )
5106 {
5107 	const auto append_quote = [&]( std::string & dest ) {
5108 		constexpr std::size_t max_quote_size = 16u;
5109 		if( error.position() > 0u )
5110 		{
5111 			// How many chars we can get from right of error position?
5112 			const auto prefix_size = error.position() > max_quote_size ?
5113 					max_quote_size : error.position();
5114 
5115 			dest.append( 1u, '"' );
5116 			dest.append(
5117 					&from[ error.position() ] - prefix_size,
5118 					prefix_size );
5119 			dest.append( "\" >>> " );
5120 		}
5121 
5122 		const char problematic_symbol = error.position() < from.size() ?
5123 				from[ error.position() ] : '?';
5124 		dest.append( 1u, '\'' );
5125 		if( problematic_symbol >= '\x00' && problematic_symbol < ' ' )
5126 		{
5127 			constexpr char hex_digits[] = "0123456789abcdef";
5128 
5129 			dest.append( "\\x" );
5130 			dest.append( 1u, hex_digits[
5131 					static_cast<unsigned char>(problematic_symbol) >> 4 ] );
5132 			dest.append( 1u, hex_digits[
5133 					static_cast<unsigned char>(problematic_symbol) & 0xfu ] );
5134 		}
5135 		else
5136 			dest.append( 1u, problematic_symbol );
5137 
5138 		dest.append( 1u, '\'' );
5139 
5140 		if( error.position() + 1u < from.size() )
5141 		{
5142 			// How many chars we can get from the right of error position?
5143 			const auto suffix_size =
5144 					error.position() + 1u + max_quote_size < from.size() ?
5145 					max_quote_size : from.size() - error.position() - 1u;
5146 
5147 			dest.append( " <<< \"" );
5148 			dest.append( &from[ error.position() + 1u ], suffix_size );
5149 			dest.append( 1u, '"' );
5150 		}
5151 	};
5152 
5153 	std::string result;
5154 
5155 	const auto basic_reaction = [&](const char * msg) {
5156 		result += msg;
5157 		result += " at ";
5158 		result += std::to_string( error.position() );
5159 		result += ": ";
5160 		append_quote( result );
5161 	};
5162 
5163 	switch( error.reason() )
5164 	{
5165 		case error_reason_t::unexpected_character:
5166 			basic_reaction( "unexpected character" );
5167 		break;
5168 
5169 		case error_reason_t::unexpected_eof:
5170 			result += "unexpected EOF at ";
5171 			result += std::to_string( error.position() );
5172 		break;
5173 
5174 		case error_reason_t::no_appropriate_alternative:
5175 			basic_reaction( "appropriate alternative can't found" );
5176 		break;
5177 
5178 		case error_reason_t::pattern_not_found:
5179 			basic_reaction( "expected pattern is not found" );
5180 		break;
5181 
5182 		case error_reason_t::unconsumed_input:
5183 			basic_reaction( "unconsumed input found" );
5184 		break;
5185 
5186 		case error_reason_t::illegal_value_found:
5187 			basic_reaction( "some illegal value found" );
5188 		break;
5189 
5190 		case error_reason_t::force_only_this_alternative_failed:
5191 			basic_reaction( "forced selection alternative failed" );
5192 		break;
5193 	}
5194 
5195 	return result;
5196 }
5197 
5198 } /* namespace easy_parser */
5199 
5200 } /* namespace restinio */
5201 
5202