From 3fec7aa458c49e8fef96a4dcf221a92a8cf9072f Mon Sep 17 00:00:00 2001 From: "Dr. Colin Hirsch" Date: Sat, 16 Dec 2023 14:42:01 +0100 Subject: [PATCH] Input refactoring in progress. --- README.md | 9 +- doc/Changelog.md | 2 + doc/Rule-Reference.md | 4 + include/tao/pegtl/analyze_traits.hpp | 7 + include/tao/pegtl/ascii.hpp | 2 +- include/tao/pegtl/contrib/function.hpp | 52 ------- include/tao/pegtl/contrib/integer.hpp | 14 +- include/tao/pegtl/contrib/raw_string.hpp | 8 +- include/tao/pegtl/internal/any.hpp | 2 +- include/tao/pegtl/internal/bump_traits.hpp | 94 +++++++---- include/tao/pegtl/internal/byteswap.hpp | 14 ++ .../tao/pegtl/internal/byteswap_gcc_clang.hpp | 41 +++++ .../{endian_win.hpp => byteswap_win32.hpp} | 20 +-- include/tao/pegtl/internal/consume.hpp | 65 ++++++++ include/tao/pegtl/internal/data_and_size.hpp | 8 +- include/tao/pegtl/internal/endian.hpp | 46 +++--- include/tao/pegtl/internal/endian_gcc.hpp | 101 ------------ include/tao/pegtl/internal/endian_system.hpp | 56 +++++++ include/tao/pegtl/internal/eol.hpp | 9 +- include/tao/pegtl/internal/function.hpp | 96 ++++++++++++ include/tao/pegtl/internal/identity.hpp | 24 +++ .../tao/pegtl/internal/input_with_peeks.hpp | 2 +- include/tao/pegtl/internal/integer_adapt.hpp | 38 +++++ include/tao/pegtl/internal/integer_size.hpp | 36 +++++ include/tao/pegtl/internal/many.hpp | 2 +- include/tao/pegtl/internal/peek_ascii.hpp | 49 ++++++ include/tao/pegtl/internal/peek_current.hpp | 32 ++++ include/tao/pegtl/internal/peek_direct.hpp | 5 - include/tao/pegtl/internal/peek_endian.hpp | 46 ++---- include/tao/pegtl/internal/peek_mask_uint.hpp | 53 ------- .../tao/pegtl/internal/peek_mask_uint8.hpp | 38 ----- include/tao/pegtl/internal/peek_masked.hpp | 43 +++++ include/tao/pegtl/internal/peek_member.hpp | 117 ++++++++++++++ include/tao/pegtl/internal/peek_utf16.hpp | 31 ++-- include/tao/pegtl/internal/peek_utf32.hpp | 20 +-- include/tao/pegtl/internal/peek_utf8.hpp | 41 +++-- include/tao/pegtl/internal/peeks.hpp | 64 ++++++++ include/tao/pegtl/internal/rules.hpp | 2 + include/tao/pegtl/internal/text_eol_bump.hpp | 4 +- include/tao/pegtl/internal/text_eol_scan.hpp | 2 +- include/tao/pegtl/internal/text_eol_tags.hpp | 12 +- include/tao/pegtl/internal/text_input.hpp | 5 +- .../pegtl/internal/text_input_with_source.hpp | 1 + include/tao/pegtl/internal/type_traits.hpp | 48 ++++++ include/tao/pegtl/internal/utility.hpp | 61 ++++++++ include/tao/pegtl/rules.hpp | 2 + include/tao/pegtl/uint16.hpp | 3 +- include/tao/pegtl/uint32.hpp | 3 +- include/tao/pegtl/uint64.hpp | 3 +- include/tao/pegtl/uint8.hpp | 3 +- .../{actions_1.cpp => action_apply_1.cpp} | 0 .../{actions_2.cpp => action_apply_2.cpp} | 0 .../{actions_3.cpp => action_apply_3.cpp} | 0 src/test/pegtl/contrib_function.cpp | 37 ----- src/test/pegtl/contrib_json.cpp | 70 ++++----- src/test/pegtl/contrib_raw_string.cpp | 33 ++-- src/test/pegtl/contrib_unescape.cpp | 10 +- ...puts_base.cpp => internal_base_inputs.cpp} | 0 src/test/pegtl/internal_endian.cpp | 116 +++++++------- src/test/pegtl/internal_inputs_lazy.cpp | 92 ----------- src/test/pegtl/internal_lazy_inputs.cpp | 95 +++++++++++ src/test/pegtl/internal_peek_member.cpp | 147 ++++++++++++++++++ ...puts_text.cpp => internal_text_inputs.cpp} | 60 +++---- src/test/pegtl/pegtl.cpp | 6 +- src/test/pegtl/rule_function.cpp | 88 +++++++++++ src/test/pegtl/test_inputs.hpp | 8 + 66 files changed, 1486 insertions(+), 716 deletions(-) delete mode 100644 include/tao/pegtl/contrib/function.hpp create mode 100644 include/tao/pegtl/internal/byteswap.hpp create mode 100644 include/tao/pegtl/internal/byteswap_gcc_clang.hpp rename include/tao/pegtl/internal/{endian_win.hpp => byteswap_win32.hpp} (68%) create mode 100644 include/tao/pegtl/internal/consume.hpp delete mode 100644 include/tao/pegtl/internal/endian_gcc.hpp create mode 100644 include/tao/pegtl/internal/endian_system.hpp create mode 100644 include/tao/pegtl/internal/function.hpp create mode 100644 include/tao/pegtl/internal/identity.hpp create mode 100644 include/tao/pegtl/internal/integer_adapt.hpp create mode 100644 include/tao/pegtl/internal/integer_size.hpp create mode 100644 include/tao/pegtl/internal/peek_ascii.hpp create mode 100644 include/tao/pegtl/internal/peek_current.hpp delete mode 100644 include/tao/pegtl/internal/peek_mask_uint.hpp delete mode 100644 include/tao/pegtl/internal/peek_mask_uint8.hpp create mode 100644 include/tao/pegtl/internal/peek_masked.hpp create mode 100644 include/tao/pegtl/internal/peek_member.hpp create mode 100644 include/tao/pegtl/internal/peeks.hpp create mode 100644 include/tao/pegtl/internal/type_traits.hpp create mode 100644 include/tao/pegtl/internal/utility.hpp rename src/test/pegtl/{actions_1.cpp => action_apply_1.cpp} (100%) rename src/test/pegtl/{actions_2.cpp => action_apply_2.cpp} (100%) rename src/test/pegtl/{actions_3.cpp => action_apply_3.cpp} (100%) delete mode 100644 src/test/pegtl/contrib_function.cpp rename src/test/pegtl/{internal_inputs_base.cpp => internal_base_inputs.cpp} (100%) delete mode 100644 src/test/pegtl/internal_inputs_lazy.cpp create mode 100644 src/test/pegtl/internal_lazy_inputs.cpp create mode 100644 src/test/pegtl/internal_peek_member.cpp rename src/test/pegtl/{internal_inputs_text.cpp => internal_text_inputs.cpp} (60%) create mode 100644 src/test/pegtl/rule_function.cpp diff --git a/README.md b/README.md index 9e355b813..d7901c29e 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,11 @@ During development of a new major version the main branch can go through incompa ## Documentation * [Changelog](doc/Changelog.md) -* [Development](doc/README.md) (requires C++17) -* [Version 3.x](https://github.com/taocpp/PEGTL/blob/3.x/doc/README.md) (requires C++17) -* [Version 2.x](https://github.com/taocpp/PEGTL/blob/2.x/doc/README.md) (requires C++11) -* [Version 1.x](https://github.com/taocpp/PEGTL/blob/1.x/doc/README.md) (requires C++11) +* [Development](doc/README.md) (C++20) +* [Version 4.x](https://github.com/taocpp/PEGTL/blob/4.x/doc/README.md) (C++17) +* [Version 3.x](https://github.com/taocpp/PEGTL/blob/3.x/doc/README.md) (C++17) +* [Version 2.x](https://github.com/taocpp/PEGTL/blob/2.x/doc/README.md) (C++11) +* [Version 1.x](https://github.com/taocpp/PEGTL/blob/1.x/doc/README.md) (C++11) ## Contact diff --git a/doc/Changelog.md b/doc/Changelog.md index da878399b..682770bfd 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -14,7 +14,9 @@ * Added new customization point for error messages. * Added optional source line output for the tracer. * Added new ASCII rules [`cntrl`](Rule-Reference.md#cntrl), [`cr`](Rule-Reference.md#cr), [`crlf`](Rule-Reference.md#crlf), [`esc`](Rule-Reference.md#esc), [`ff`](Rule-Reference.md#ff), [`graph`](Rule-Reference.md#graph), [`ht`](Rule-Reference.md#ht), [`lf`](Rule-Reference.md#lf), [`lfcr`](Rule-Reference.md#lfcr), [`sp`](Rule-Reference.md#sp), [`vt`](Rule-Reference.md#vt). +* Added new atomic rule [`consume`](Rule-Reference.md#consume-count-). * Added new atomic rule [`everything`](Rule-Reference.md#everything). +* Added new rule [`invert`](Rule-Reference.md#invert-r-) to convert between `one` and `not_one` etc. * Added new convenience rule [`partial`](Rule-Reference.md#partial-r-). * Added new convenience rule [`star_partial`](Rule-Reference.md#star_partial-r-). * Added new convenience rule [`strict`](Rule-Reference.md#strict-r-). diff --git a/doc/Rule-Reference.md b/doc/Rule-Reference.md index 485a387b1..ddb4b08b3 100644 --- a/doc/Rule-Reference.md +++ b/doc/Rule-Reference.md @@ -667,6 +667,10 @@ Atomic rules do not rely on other rules. * [Meta data] and [implementation] mapping: - `bol::rule_t` is `internal::bol` +###### `consume< Count >` + +TODO + ###### `eof` * Succeeds at "end-of-file", i.e. when the input is empty or all input has been consumed. diff --git a/include/tao/pegtl/analyze_traits.hpp b/include/tao/pegtl/analyze_traits.hpp index 236edf2f4..e7601a130 100644 --- a/include/tao/pegtl/analyze_traits.hpp +++ b/include/tao/pegtl/analyze_traits.hpp @@ -90,6 +90,11 @@ namespace TAO_PEGTL_NAMESPACE : analyze_opt_traits<> {}; + template< typename Name, std::size_t Count > + struct analyze_traits< Name, internal::consume< Count > > + : std::conditional_t< ( Count > 0 ), analyze_any_traits<>, analyze_opt_traits<> > + {}; + template< typename Name, template< typename... > class Control, typename... Rules > struct analyze_traits< Name, internal::control< Control, Rules... > > : analyze_traits< Name, typename seq< Rules... >::rule_t > @@ -130,6 +135,8 @@ namespace TAO_PEGTL_NAMESPACE : analyze_any_traits<> {}; + // No general analyze_traits for internal::function<> for obvious reasons. + template< typename Name, typename Rule, typename... Actions > struct analyze_traits< Name, internal::if_apply< Rule, Actions... > > : analyze_traits< Name, typename Rule::rule_t > diff --git a/include/tao/pegtl/ascii.hpp b/include/tao/pegtl/ascii.hpp index 56473ae89..3fdf00940 100644 --- a/include/tao/pegtl/ascii.hpp +++ b/include/tao/pegtl/ascii.hpp @@ -7,7 +7,7 @@ #include "config.hpp" -#include "internal/peek_direct.hpp" +#include "internal/peeks.hpp" #include "internal/result_on_found.hpp" #include "internal/rules.hpp" diff --git a/include/tao/pegtl/contrib/function.hpp b/include/tao/pegtl/contrib/function.hpp deleted file mode 100644 index 91d1ef029..000000000 --- a/include/tao/pegtl/contrib/function.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2020-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#ifndef TAO_PEGTL_CONTRIB_FUNCTION_HPP -#define TAO_PEGTL_CONTRIB_FUNCTION_HPP - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" -#include "../type_list.hpp" - -#include "../internal/enable_control.hpp" - -namespace TAO_PEGTL_NAMESPACE -{ - namespace internal - { - template< typename F, F U > - struct function; - - template< typename ParseInput, typename... States, bool ( *U )( ParseInput&, States... ) > - struct function< bool ( * )( ParseInput&, States... ), U > - { - using rule_t = function; - using subs_t = empty_list; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - [[nodiscard]] static bool match( ParseInput& in, States... st ) noexcept( noexcept( U( in, st... ) ) ) - { - return U( in, st... ); - } - }; - - template< typename F, F U > - inline constexpr bool enable_control< function< F, U > > = false; - - } // namespace internal - - template< auto F > - struct function - : internal::function< decltype( F ), F > - {}; - -} // namespace TAO_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/pegtl/contrib/integer.hpp b/include/tao/pegtl/contrib/integer.hpp index d956332de..61cb4c12b 100644 --- a/include/tao/pegtl/contrib/integer.hpp +++ b/include/tao/pegtl/contrib/integer.hpp @@ -23,6 +23,8 @@ #include "../parse_error.hpp" #include "../rules.hpp" +#include "../internal/text_eol_tags.hpp" + namespace TAO_PEGTL_NAMESPACE { struct unsigned_rule_old @@ -153,12 +155,12 @@ namespace TAO_PEGTL_NAMESPACE if( !in.empty() ) { const char c = in.peek_char(); if( is_digit( c ) ) { - in.template consume< unsigned >( 1 ); + in.template consume< eol_exclude_tag >( 1 ); if( c == '0' ) { return in.empty() || ( !is_digit( in.peek_char() ) ); } while( ( !in.empty() ) && is_digit( in.peek_char() ) ) { - in.template consume< unsigned >( 1 ); + in.template consume< eol_exclude_tag >( 1 ); } return true; } @@ -177,14 +179,14 @@ namespace TAO_PEGTL_NAMESPACE char c = in.peek_char(); if( is_digit( c ) ) { if( c == '0' ) { - in.template consume< unsigned >( 1 ); + in.template consume< eol_exclude_tag >( 1 ); return in.empty() || ( !is_digit( in.peek_char() ) ); } do { if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) { throw TAO_PEGTL_NAMESPACE::parse_error( "integer overflow", in ); } - in.template consume< unsigned >( 1 ); + in.template consume< eol_exclude_tag >( 1 ); } while( ( !in.empty() ) && is_digit( c = in.peek_char() ) ); return true; } @@ -203,7 +205,7 @@ namespace TAO_PEGTL_NAMESPACE char c = in.peek_char(); if( c == '0' ) { if( ( in.size( 2 ) < 2 ) || ( !is_digit( in.peek_char( 1 ) ) ) ) { - in.template consume< unsigned >( 1 ); + in.template consume< eol_exclude_tag >( 1 ); return true; } return false; @@ -217,7 +219,7 @@ namespace TAO_PEGTL_NAMESPACE } ++b; } while( ( !in.empty() ) && is_digit( c = in.peek_char( b ) ) ); - in.template consume< unsigned >( b ); + in.template consume< eol_exclude_tag >( b ); return true; } } diff --git a/include/tao/pegtl/contrib/raw_string.hpp b/include/tao/pegtl/contrib/raw_string.hpp index 6a46ffe49..efc628e95 100644 --- a/include/tao/pegtl/contrib/raw_string.hpp +++ b/include/tao/pegtl/contrib/raw_string.hpp @@ -16,6 +16,8 @@ #include "../rewind_mode.hpp" #include "../rules.hpp" +#include "../internal/text_eol_tags.hpp" + namespace TAO_PEGTL_NAMESPACE { namespace internal @@ -42,7 +44,7 @@ namespace TAO_PEGTL_NAMESPACE switch( const auto c = in.peek_char( i ) ) { case Open: marker_size = i + 1; - in.template consume< raw_string_open >( marker_size ); + in.template consume< eol_exclude_tag >( marker_size ); (void)Control< eol >::template match< A, M, Action, Control >( in ); return true; case Marker: @@ -121,7 +123,7 @@ namespace TAO_PEGTL_NAMESPACE if( in.empty() ) { return false; } - in.template consume< raw_string_until >( 1 ); + in.template consume< eol_unknown_tag >( 1 ); } return m( true ); } @@ -209,7 +211,7 @@ namespace TAO_PEGTL_NAMESPACE std::size_t marker_size; if( Control< internal::raw_string_open< Open, Marker > >::template match< A, M, Action, Control >( in, marker_size ) ) { if( Control< content >::template match< A, M, Action, Control >( in, marker_size, st... ) ) { - in.template consume< raw_string >( marker_size ); + in.template consume< internal::eol_exclude_tag >( marker_size ); return true; } } diff --git a/include/tao/pegtl/internal/any.hpp b/include/tao/pegtl/internal/any.hpp index 6eea218a6..7247d2b4e 100644 --- a/include/tao/pegtl/internal/any.hpp +++ b/include/tao/pegtl/internal/any.hpp @@ -9,7 +9,7 @@ #include "../type_list.hpp" #include "enable_control.hpp" -#include "peek_direct.hpp" +#include "peeks.hpp" namespace TAO_PEGTL_NAMESPACE::internal { diff --git a/include/tao/pegtl/internal/bump_traits.hpp b/include/tao/pegtl/internal/bump_traits.hpp index 430f0dd20..80b11edef 100644 --- a/include/tao/pegtl/internal/bump_traits.hpp +++ b/include/tao/pegtl/internal/bump_traits.hpp @@ -6,31 +6,24 @@ #define TAO_PEGTL_INTERNAL_BUMP_TRAITS_HPP #include +#include #include "../config.hpp" #include "any.hpp" +#include "at.hpp" +#include "eol.hpp" +#include "eolf.hpp" +#include "consume.hpp" +#include "everything.hpp" #include "many.hpp" #include "text_eol_tags.hpp" +#include "until.hpp" namespace TAO_PEGTL_NAMESPACE::internal { template< typename Eol, typename Rule, typename = void > - struct bump_traits - { - // template< typename Data, typename Position > - // static void bump( Position& pos, const Data* /*unused*/, const std::size_t count ) noexcept - // { - // pos.column += count; - // pos.count += count; - // } - - template< typename Data, typename Position > - static void bump( Position& pos, const Data* data, const std::size_t count ) noexcept - { - text_eol_scan< Eol >( pos, data, data + count ); - } - }; + struct bump_traits; template< typename Eol > struct bump_traits< Eol, eol_exclude_tag > @@ -50,7 +43,7 @@ namespace TAO_PEGTL_NAMESPACE::internal static void bump( Position& pos, const Data* /*unused*/, const std::size_t count ) noexcept { pos.line++; - pos.column = 1; // TODO: Incrementing column while matching Eol is redundant! + pos.column = 1; pos.count += count; } }; @@ -65,25 +58,66 @@ namespace TAO_PEGTL_NAMESPACE::internal } }; + template< typename Eol, typename Rule > + struct bump_traits< Eol, Rule, std::enable_if_t< std::is_same_v< Eol, Rule > > > + : bump_traits< Eol, eol_matched_tag > + {}; + + // TODO: Anything else to detect and optimise eol_rule sub-rules? + template< typename Eol, typename Peek > struct bump_traits< Eol, any< Peek > > - { - template< typename Data, typename Position > - static void bump( Position& pos, const Data* data, const std::size_t count ) - { - text_eol_scan< Eol >( pos, data, data + count ); - } - }; + : bump_traits< Eol, eol_unknown_tag > // TODO: Only when single-char eol possible? + {}; + + template< typename Eol, unsigned Count > + struct bump_traits< Eol, consume< Count > > + : bump_traits< Eol, eol_unknown_tag > + {}; + + template< typename Eol, typename Size > + struct bump_traits< Eol, everything< Size > > + : bump_traits< Eol, eol_unknown_tag > + {}; template< typename Eol, unsigned Count, typename Peek > struct bump_traits< Eol, many< Count, Peek > > - { - template< typename Data, typename Position > - static void bump( Position& pos, const Data* data, const std::size_t count ) - { - text_eol_scan< Eol >( pos, data, data + count ); - } - }; + : bump_traits< Eol, eol_unknown_tag > + {}; + + template< typename Eol, typename Cond > + struct bump_traits< Eol, until< Cond > > + : bump_traits< Eol, eol_unknown_tag > + {}; + + template< typename Eol > + struct bump_traits< Eol, until< eol > > + : bump_traits< Eol, eol_exclude_tag > + {}; + + template< typename Eol > + struct bump_traits< Eol, until< eolf > > + : bump_traits< Eol, eol_exclude_tag > + {}; + + template< typename Eol, typename Cond > + struct bump_traits< Eol, until< Cond >, std::enable_if_t< std::is_same_v< Eol, Cond > > > + : bump_traits< Eol, eol_exclude_tag > + {}; + + template< typename Eol, typename Cond > + struct bump_traits< Eol, until< at< Cond > > > + : bump_traits< Eol, until< typename Cond::rule_t > > + {}; + + // TODO: Anything else that can be made independent of the default case? + // TODO: Most importantly: one, range(s), (i)string (and the ICU rules?) + + template< typename Eol, typename Rule, typename > + struct bump_traits + : bump_traits< Eol, eol_unknown_tag > // check + // : bump_traits< Eol, eol_exclude_tag > // trust + {}; } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/include/tao/pegtl/internal/byteswap.hpp b/include/tao/pegtl/internal/byteswap.hpp new file mode 100644 index 000000000..4113ab26d --- /dev/null +++ b/include/tao/pegtl/internal/byteswap.hpp @@ -0,0 +1,14 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_BYTESWAP_HPP +#define TAO_PEGTL_INTERNAL_BYTESWAP_HPP + +#if defined( _WIN32 ) && !defined( __MINGW32__ ) && !defined( __CYGWIN__ ) +#include "byteswap_win32.hpp" +#else +#include "byteswap_gcc_clang.hpp" +#endif + +#endif diff --git a/include/tao/pegtl/internal/byteswap_gcc_clang.hpp b/include/tao/pegtl/internal/byteswap_gcc_clang.hpp new file mode 100644 index 000000000..0c6a01701 --- /dev/null +++ b/include/tao/pegtl/internal/byteswap_gcc_clang.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_BYTESWAP_GCC_CLANG_HPP +#define TAO_PEGTL_INTERNAL_BYTESWAP_GCC_CLANG_HPP + +#include +#include + +#include "../config.hpp" + +#include "dependent_false.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename T > + [[nodiscard]] T byteswap( const T n ) noexcept + { + static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); + + if constexpr( sizeof( T ) == 1 ) { + return n; + } + else if constexpr( sizeof( T ) == 2 ) { + return static_cast< T >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); + } + else if constexpr( sizeof( T ) == 4 ) { + return static_cast< T >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); + } + else if constexpr( sizeof( T ) == 8 ) { + return static_cast< T >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); + } + else { + static_assert( dependent_false< T > ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/endian_win.hpp b/include/tao/pegtl/internal/byteswap_win32.hpp similarity index 68% rename from include/tao/pegtl/internal/endian_win.hpp rename to include/tao/pegtl/internal/byteswap_win32.hpp index e0aadf3a5..92b3ea1c3 100644 --- a/include/tao/pegtl/internal/endian_win.hpp +++ b/include/tao/pegtl/internal/byteswap_win32.hpp @@ -2,8 +2,8 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) -#ifndef TAO_PEGTL_INTERNAL_ENDIAN_WIN_HPP -#define TAO_PEGTL_INTERNAL_ENDIAN_WIN_HPP +#ifndef TAO_PEGTL_INTERNAL_BYTESWAP_WIN32_HPP +#define TAO_PEGTL_INTERNAL_BYTESWAP_WIN32_HPP #include #include @@ -14,19 +14,8 @@ namespace TAO_PEGTL_NAMESPACE::internal { - // Windows has never and will never do big endian? - -#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## le - - template< typename T > - T little_endian::from( const T n ) noexcept - { - static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); - return n; - } - template< typename T > - T big_endian::from( const T n ) noexcept + [[nodiscard]] T byteswap( const T n ) noexcept { static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); @@ -47,9 +36,6 @@ namespace TAO_PEGTL_NAMESPACE::internal } } - using other_endian = big_endian; - using native_endian = little_endian; - } // namespace TAO_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/pegtl/internal/consume.hpp b/include/tao/pegtl/internal/consume.hpp new file mode 100644 index 000000000..a4ee33f15 --- /dev/null +++ b/include/tao/pegtl/internal/consume.hpp @@ -0,0 +1,65 @@ +// Copyright (c) 2017-2022 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_CONSUME_HPP +#define TAO_PEGTL_INTERNAL_CONSUME_HPP + +#include + +#include "../config.hpp" +#include "../type_list.hpp" + +#include "enable_control.hpp" +#include "success.hpp" +#include "utility.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< std::size_t Count, typename Reference = void > + struct consume + { + using rule_t = consume; + using subs_t = empty_list; + + template< typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in ) noexcept + { + static_assert( is_integer_fraction( sizeof( Reference ), sizeof( *in.current() ) ) ); + + if( in.size( Count ) >= Count ) { + in.template consume< consume >( Count ); + return true; + } + return false; + } + }; + + template< typename Reference > + struct consume< 0, Reference > + : success + {}; + + template< std::size_t Count > + struct consume< Count, void > + { + using rule_t = consume; + using subs_t = empty_list; + + template< typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in ) noexcept + { + if( in.size( Count ) >= Count ) { + in.template consume< consume >( Count ); + return true; + } + return false; + } + }; + + template< unsigned Count, typename Reference > + inline constexpr bool enable_control< consume< Count, Reference > > = false; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/data_and_size.hpp b/include/tao/pegtl/internal/data_and_size.hpp index d15430fe6..82fa0c974 100644 --- a/include/tao/pegtl/internal/data_and_size.hpp +++ b/include/tao/pegtl/internal/data_and_size.hpp @@ -42,11 +42,6 @@ namespace TAO_PEGTL_NAMESPACE::internal return m_size > 0; } - void mask_with( const Data mask ) noexcept - { - m_data &= mask; - } - private: Data m_data; Size m_size = 0; @@ -85,6 +80,9 @@ namespace TAO_PEGTL_NAMESPACE::internal const Data* m_data = nullptr; }; + template< typename Data > + data_and_size( const Data* ) -> data_and_size< Data, void >; + } // namespace TAO_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/pegtl/internal/endian.hpp b/include/tao/pegtl/internal/endian.hpp index 56d17ef9b..2afed34cc 100644 --- a/include/tao/pegtl/internal/endian.hpp +++ b/include/tao/pegtl/internal/endian.hpp @@ -5,46 +5,48 @@ #ifndef TAO_PEGTL_INTERNAL_ENDIAN_HPP #define TAO_PEGTL_INTERNAL_ENDIAN_HPP -#include - #include "../config.hpp" +#include "byteswap.hpp" +#include "endian_system.hpp" +#include "identity.hpp" +#include "integer_adapt.hpp" + namespace TAO_PEGTL_NAMESPACE::internal { - struct big_endian + struct identity_endian { template< typename T > - [[nodiscard]] static T from( const T n ) noexcept; + [[nodiscard]] static T get( const T data ) noexcept + { + return identity( data ); + } - template< typename T > - [[nodiscard]] static T from( const void* p ) noexcept + template< typename T, typename Data > + [[nodiscard]] static T get( const Data* pointer ) noexcept { - T n; - std::memcpy( &n, p, sizeof( n ) ); - return from( n ); + return identity( integer_adapt< T >( pointer ) ); } }; - struct little_endian + struct byteswap_endian { template< typename T > - [[nodiscard]] static T from( const T n ) noexcept; + [[nodiscard]] static T get( const T data ) noexcept + { + return byteswap( data ); + } - template< typename T > - [[nodiscard]] static T from( const void* p ) noexcept + template< typename T, typename Data > + [[nodiscard]] static T get( const Data* pointer ) noexcept { - T n; - std::memcpy( &n, p, sizeof( n ) ); - return from( n ); + return byteswap( integer_adapt< T >( pointer ) ); } }; -} // namespace TAO_PEGTL_NAMESPACE::internal + using big_endian = TAO_PEGTL_BIG_ENDIAN_TYPE; + using little_endian = TAO_PEGTL_LITTLE_ENDIAN_TYPE; -#if defined( _WIN32 ) && !defined( __MINGW32__ ) && !defined( __CYGWIN__ ) -#include "endian_win.hpp" -#else -#include "endian_gcc.hpp" -#endif +} // namespace TAO_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/pegtl/internal/endian_gcc.hpp b/include/tao/pegtl/internal/endian_gcc.hpp deleted file mode 100644 index e64a7c707..000000000 --- a/include/tao/pegtl/internal/endian_gcc.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2017-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#ifndef TAO_PEGTL_INTERNAL_ENDIAN_GCC_HPP -#define TAO_PEGTL_INTERNAL_ENDIAN_GCC_HPP - -#include -#include - -#include "../config.hpp" - -#include "dependent_false.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ -#if !defined( __BYTE_ORDER__ ) -#error No byte order defined! -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - -#define TAO_PEGTL_BIG_ENDIAN 1 - -#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## be - - template< typename T > - T big_endian::from( const T n ) noexcept - { - static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); - return n; - } - - template< typename T > - T little_endian::from( const T n ) noexcept - { - static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); - - if constexpr( sizeof( T ) == 1 ) { - return n; - } - else if constexpr( sizeof( T ) == 2 ) { - return static_cast< T >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); - } - else if constexpr( sizeof( T ) == 4 ) { - return static_cast< T >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); - } - else if constexpr( sizeof( T ) == 8 ) { - return static_cast< T >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); - } - else { - static_assert( dependent_false< T > ); - } - } - - using other_endian = little_endian; - using native_endian = big_endian; - -#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -#define TAO_PEGTL_LITTLE_ENDIAN 1 - -#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## le - - template< typename T > - T little_endian::from( const T n ) noexcept - { - static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); - return n; - } - - template< typename T > - T big_endian::from( const T n ) noexcept - { - static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); - - if constexpr( sizeof( T ) == 1 ) { - return n; - } - else if constexpr( sizeof( T ) == 2 ) { - return static_cast< T >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); - } - else if constexpr( sizeof( T ) == 4 ) { - return static_cast< T >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); - } - else if constexpr( sizeof( T ) == 8 ) { - return static_cast< T >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); - } - else { - static_assert( dependent_false< T > ); - } - } - - using other_endian = big_endian; - using native_endian = little_endian; - -#else -#error Unknown byte order! -#endif - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/pegtl/internal/endian_system.hpp b/include/tao/pegtl/internal/endian_system.hpp new file mode 100644 index 000000000..68f0dda2b --- /dev/null +++ b/include/tao/pegtl/internal/endian_system.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2017-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_ENDIAN_SYSTEM_HPP +#define TAO_PEGTL_INTERNAL_ENDIAN_SYSTEM_HPP + +#if defined( _WIN32 ) + +#if !defined( __ORDER_BIG_ENDIAN__ ) +#define __ORDER_BIG_ENDIAN__ 4321 +#endif + +#if !defined( __ORDER_LITTLE_ENDIAN__ ) +#define __ORDER_LITTLE_ENDIAN__ 1234 +#endif + +#if !defined( __BYTE__ORDER__ ) +#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +#endif + +#define TAO_PEGTL_BIG_ENDIAN_TYPE byteswap_endian +#define TAO_PEGTL_LITTLE_ENDIAN_TYPE identity_endian + +#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## le + +// NOTE: I'm pretty sure that all Windows versions ever are little +// endian, including on processors like Alpha, Mips and Itanium. + +#elif !defined( __BYTE_ORDER__ ) + +#error No byte order defined even though we are not on Windows! + +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +#define TAO_PEGTL_BIG_ENDIAN_TYPE identity_endian +#define TAO_PEGTL_LITTLE_ENDIAN_TYPE byteswap_endian + +#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## be + +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + +#define TAO_PEGTL_BIG_ENDIAN_TYPE byteswap_endian +#define TAO_PEGTL_LITTLE_ENDIAN_TYPE identity_endian + +#define TAO_PEGTL_ENDIAN_SUFFIXED( iDeNTiFieR ) iDeNTiFieR ## le + +#else + +#error Byte order is neither big nor little endian and we do NOT support the PDP-11! + +#endif + +#define TAO_PEGTL_PASTE_ENDIAN_SYMBOLS( FiRST, SeCoND ) FiRST ## SeCoND + +#endif diff --git a/include/tao/pegtl/internal/eol.hpp b/include/tao/pegtl/internal/eol.hpp index 0cf130234..51954335f 100644 --- a/include/tao/pegtl/internal/eol.hpp +++ b/include/tao/pegtl/internal/eol.hpp @@ -18,7 +18,7 @@ namespace TAO_PEGTL_NAMESPACE::internal struct eol { using rule_t = eol; - using subs_t = empty_list; // Should be eol_rule, but we don't know that here yet... + using subs_t = empty_list; // Not quite true, but good enough and we can't really do better. template< apply_mode A, rewind_mode M, @@ -31,11 +31,8 @@ namespace TAO_PEGTL_NAMESPACE::internal [[nodiscard]] static bool match( ParseInput& in, States&&... st ) { using eol_rule = typename ParseInput::eol_rule; - if( Control< typename eol_rule::rule_t >::template match< A, M, Action, Control >( in, st... ) ) { - // in.template consume< eol_matched_tag >( 0 ); // TODO: Can we optimise the above line to not perform position updates and do this instead? - return true; - } - return false; + using eol_impl = typename eol_rule::rule_t; + return Control< eol_impl >::template match< apply_mode::nothing, M, Action, Control >( in, st... ); } }; diff --git a/include/tao/pegtl/internal/function.hpp b/include/tao/pegtl/internal/function.hpp new file mode 100644 index 000000000..a97f2f10f --- /dev/null +++ b/include/tao/pegtl/internal/function.hpp @@ -0,0 +1,96 @@ +// Copyright (c) 2020-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_FUNCTION_HPP +#define TAO_PEGTL_INTERNAL_FUNCTION_HPP + +#include + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../rewind_mode.hpp" +#include "../type_list.hpp" + +#include "enable_control.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename Func, Func Tion, typename Peek > + struct function; + + template< bool E, typename Input, typename... States, bool ( *Tion )( Input&, States... ) noexcept( E ) > + struct function< bool ( * )( Input&, States... ) noexcept( E ), Tion, void > + { + using rule_t = function; + using subs_t = empty_list; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in, States... st ) noexcept( E ) + { + return Tion( in, st... ); + } + }; + + template< bool E, typename Data, bool ( *Tion )( Data ) noexcept( E ), typename Peek > + struct function< bool ( * )( Data ) noexcept( E ), Tion, Peek > + { + using peek_t = Peek; + // using data_t = typename Peek::data_t; + + using rule_t = function; + using subs_t = empty_list; + + template< typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in ) + { + if( const auto t = Peek::peek( in ) ) { + if( Tion( t.data() ) ) { + in.template consume< function >( t.size() ); + return true; + } + } + return false; + } + }; + + template< bool E, typename Data, typename... States, bool ( *Tion )( Data, States... ) noexcept( E ), typename Peek > + struct function< bool ( * )( Data, States... ) noexcept( E ), Tion, Peek > + { + using peek_t = Peek; + // using data_t = typename Peek::data_t; + + using rule_t = function; + using subs_t = empty_list; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in, States... st ) + { + if( const auto t = Peek::peek( in ) ) { + if( Tion( t.data(), st... ) ) { + in.template consume< function >( t.size() ); + return true; + } + } + return false; + } + }; + + template< typename Func, Func Tion, typename Peek > + inline constexpr bool enable_control< function< Func, Tion, Peek > > = false; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/identity.hpp b/include/tao/pegtl/internal/identity.hpp new file mode 100644 index 000000000..ed9936d24 --- /dev/null +++ b/include/tao/pegtl/internal/identity.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_IDENTITY_HPP +#define TAO_PEGTL_INTERNAL_IDENTITY_HPP + +#include + +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename T > + [[nodiscard]] T identity( const T n ) noexcept + { + static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); + // ...or will anybody ever parse sequences of floats or doubles? + return n; + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/input_with_peeks.hpp b/include/tao/pegtl/internal/input_with_peeks.hpp index 184c6c6bc..e4b7ffe8f 100644 --- a/include/tao/pegtl/internal/input_with_peeks.hpp +++ b/include/tao/pegtl/internal/input_with_peeks.hpp @@ -55,7 +55,7 @@ namespace TAO_PEGTL_NAMESPACE::internal return peek_as< std::uint8_t >( offset ); } - // [[nodiscard]] std::span< data_t > span() const noexcept + // [[nodiscard]] std::span< data_t > span() const noexcept // TODO: With C++20. [[nodiscard]] std::string string() const { diff --git a/include/tao/pegtl/internal/integer_adapt.hpp b/include/tao/pegtl/internal/integer_adapt.hpp new file mode 100644 index 000000000..5eafe3876 --- /dev/null +++ b/include/tao/pegtl/internal/integer_adapt.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_INTEGER_ADAPT_HPP +#define TAO_PEGTL_INTERNAL_INTEGER_ADAPT_HPP + +#include +#include + +#include "../config.hpp" + +#include "dependent_false.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename T, typename Data > + [[nodiscard]] T integer_adapt( const Data* pointer ) noexcept + { + static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); + static_assert( std::is_integral_v< Data > || std::is_enum_v< Data > ); + + if constexpr( sizeof( T ) == sizeof( Data ) ) { + return static_cast< T >( *pointer ); + } + else if constexpr( sizeof( Data ) == 1 ) { + T result; + std::memcpy( &result, pointer, sizeof( result ) ); + return result; + } + else { + static_assert( dependent_false< Data > ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/integer_size.hpp b/include/tao/pegtl/internal/integer_size.hpp new file mode 100644 index 000000000..9e9f960b6 --- /dev/null +++ b/include/tao/pegtl/internal/integer_size.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_INTEGER_SIZE_HPP +#define TAO_PEGTL_INTERNAL_INTEGER_SIZE_HPP + +#include +#include + +#include "../config.hpp" + +#include "dependent_false.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename T, typename Data > + [[nodiscard]] std::size_t integer_size( const Data* /*unused*/ ) noexcept + { + static_assert( std::is_integral_v< T > || std::is_enum_v< T > ); + static_assert( std::is_integral_v< Data > || std::is_enum_v< Data > ); + + if constexpr( sizeof( T ) == sizeof( Data ) ) { + return 1; + } + else if constexpr( sizeof( Data ) == 1 ) { + return sizeof( T ); + } + else { + static_assert( dependent_false< Data > ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/many.hpp b/include/tao/pegtl/internal/many.hpp index e242c5681..e9856e119 100644 --- a/include/tao/pegtl/internal/many.hpp +++ b/include/tao/pegtl/internal/many.hpp @@ -40,7 +40,7 @@ namespace TAO_PEGTL_NAMESPACE::internal } else if constexpr( sizeof( *in.current() ) == 1 ) { static_assert( Peek::fixed_size > 0 ); - if( in.size( Count * Peek::fixed_size ) >= Count * Peek::fixed_size ) { + if( in.size( Count * Peek::fixed_size ) >= ( Count * Peek::fixed_size ) ) { in.template consume< many >( Count * Peek::fixed_size ); return true; } diff --git a/include/tao/pegtl/internal/peek_ascii.hpp b/include/tao/pegtl/internal/peek_ascii.hpp new file mode 100644 index 000000000..013e49896 --- /dev/null +++ b/include/tao/pegtl/internal/peek_ascii.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2021-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_PEEK_ASCII_HPP +#define TAO_PEGTL_INTERNAL_PEEK_ASCII_HPP + +#include +#include + +#include "../config.hpp" + +#include "data_and_size.hpp" +#include "endian.hpp" +#include "type_traits.hpp" +#include "utility.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename Endian > + struct peek_ascii_impl + { + using data_t = char; + using pair_t = data_and_size< data_t >; + + static constexpr bool allow_bulk = false; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( sizeof( data_t ) ) ) ) + { + using temp_t = typename integer_traits< sizeof( *in.current() ) >::unsigned_t; + + if( in.size( 1 + offset ) >= ( 1 + offset ) ) { + const temp_t t = Endian::template get< temp_t >( in.current( offset ) ); + if( is_ascii_value( t ) ) { + return pair_t( char( t ), 1 ); + } + } + return pair_t(); + } + }; + + using peek_ascii = peek_ascii_impl< identity_endian >; + using peek_ascii_be = peek_ascii_impl< big_endian >; + using peek_ascii_le = peek_ascii_impl< little_endian >; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/peek_current.hpp b/include/tao/pegtl/internal/peek_current.hpp new file mode 100644 index 000000000..f2b6fc64b --- /dev/null +++ b/include/tao/pegtl/internal/peek_current.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2014-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_PEEK_CURRENT_HPP +#define TAO_PEGTL_INTERNAL_PEEK_CURRENT_HPP + +#include +#include + +#include "data_and_size.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + struct peek_current + { + // using data_t = Depends on ParseInput. + // using pair_t = Depends on ParseInput. + + static constexpr bool allow_bulk = true; + static constexpr std::size_t fixed_size = 1; + + template< typename ParseInput > + [[nodiscard]] static auto peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 42 ) ) ) + { + return data_and_size( ( in.size( offset + 1 ) >= ( offset + 1 ) ) ? in.current( offset ) : nullptr ); + } + }; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/peek_direct.hpp b/include/tao/pegtl/internal/peek_direct.hpp index 53b479cb7..f5190a161 100644 --- a/include/tao/pegtl/internal/peek_direct.hpp +++ b/include/tao/pegtl/internal/peek_direct.hpp @@ -35,11 +35,6 @@ namespace TAO_PEGTL_NAMESPACE::internal } }; - using peek_char = peek_direct< char >; - using peek_int8 = peek_direct< std::int8_t >; - using peek_uint8 = peek_direct< std::uint8_t >; - using peek_byte = peek_direct< std::byte >; - } // namespace TAO_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/pegtl/internal/peek_endian.hpp b/include/tao/pegtl/internal/peek_endian.hpp index db692645e..09760d6e5 100644 --- a/include/tao/pegtl/internal/peek_endian.hpp +++ b/include/tao/pegtl/internal/peek_endian.hpp @@ -11,8 +11,8 @@ #include "../config.hpp" #include "data_and_size.hpp" -#include "dependent_false.hpp" #include "endian.hpp" +#include "integer_size.hpp" namespace TAO_PEGTL_NAMESPACE::internal { @@ -20,52 +20,24 @@ namespace TAO_PEGTL_NAMESPACE::internal struct peek_endian { using data_t = Data; - using pair_t = data_and_size< Data >; - - static_assert( sizeof( Data ) > 1 ); + using pair_t = data_and_size< data_t >; static constexpr bool allow_bulk = true; - static constexpr std::size_t fixed_size = sizeof( Data ); + static constexpr std::size_t fixed_size = sizeof( data_t ); template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 42 ) ) ) + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( sizeof( data_t ) ) ) ) { - using peek_t = typename ParseInput::data_t; + const std::size_t s = integer_size< data_t >( in.current() ); - if constexpr( sizeof( peek_t ) == 1 ) { - if( in.size( sizeof( Data ) + offset ) < sizeof( Data ) + offset ) { - return pair_t(); - } - return pair_t( Endian::template from< Data >( in.current( offset ) ), sizeof( Data ) ); - } - else if constexpr( sizeof( peek_t ) == sizeof( Data ) ) { - if( in.size( 1 + offset ) < 1 + offset ) { - return pair_t(); - } - return pair_t( Endian::template from< Data >( *in.current( offset ) ), 1 ); - } - else { - static_assert( dependent_false< peek_endian > ); + if( in.size( s + offset ) >= ( s + offset ) ) { + const data_t t = Endian::template get< data_t >( in.current( offset ) ); + return pair_t( t, s ); } + return pair_t(); } }; - using peek_int16_be = peek_endian< std::int16_t, big_endian >; - using peek_int32_be = peek_endian< std::int32_t, big_endian >; - using peek_int64_be = peek_endian< std::int64_t, big_endian >; - - using peek_int16_le = peek_endian< std::int16_t, little_endian >; - using peek_int32_le = peek_endian< std::int32_t, little_endian >; - using peek_int64_le = peek_endian< std::int64_t, little_endian >; - - using peek_uint16_be = peek_endian< std::uint16_t, big_endian >; - using peek_uint32_be = peek_endian< std::uint32_t, big_endian >; - using peek_uint64_be = peek_endian< std::uint64_t, big_endian >; - - using peek_uint16_le = peek_endian< std::uint16_t, little_endian >; - using peek_uint32_le = peek_endian< std::uint32_t, little_endian >; - using peek_uint64_le = peek_endian< std::uint64_t, little_endian >; - } // namespace TAO_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/pegtl/internal/peek_mask_uint.hpp b/include/tao/pegtl/internal/peek_mask_uint.hpp deleted file mode 100644 index 3025f1491..000000000 --- a/include/tao/pegtl/internal/peek_mask_uint.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#ifndef TAO_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP -#define TAO_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP - -#include -#include - -#include "data_and_size.hpp" -#include "endian.hpp" -#include "peek_endian.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - template< typename Data, Data Mask, typename Endian > - struct peek_mask_uint_impl - { - using data_t = Data; - using pair_t = data_and_size< data_t >; - - static_assert( sizeof( Data ) > 1 ); - - static constexpr bool allow_bulk = true; - static constexpr std::size_t fixed_size = sizeof( Data ); - - template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( sizeof( data_t ) ) ) ) - { - pair_t r = peek_endian< Data, Endian >::peek( in, offset ); - r.mask_with( Mask ); - return r; - } - }; - - template< std::uint16_t Mask > - using peek_mask_uint16_be = peek_mask_uint_impl< std::uint16_t, Mask, big_endian >; - template< std::uint32_t Mask > - using peek_mask_uint32_be = peek_mask_uint_impl< std::uint32_t, Mask, big_endian >; - template< std::uint64_t Mask > - using peek_mask_uint64_be = peek_mask_uint_impl< std::uint64_t, Mask, big_endian >; - - template< std::uint16_t Mask > - using peek_mask_uint16_le = peek_mask_uint_impl< std::uint16_t, Mask, little_endian >; - template< std::uint32_t Mask > - using peek_mask_uint32_le = peek_mask_uint_impl< std::uint32_t, Mask, little_endian >; - template< std::uint64_t Mask > - using peek_mask_uint64_le = peek_mask_uint_impl< std::uint64_t, Mask, little_endian >; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/pegtl/internal/peek_mask_uint8.hpp b/include/tao/pegtl/internal/peek_mask_uint8.hpp deleted file mode 100644 index 580a03078..000000000 --- a/include/tao/pegtl/internal/peek_mask_uint8.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#ifndef TAO_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP -#define TAO_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP - -#include -#include - -#include "data_and_size.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - template< std::uint8_t M > - struct peek_mask_uint8 - { - using data_t = std::uint8_t; - using pair_t = data_and_size< std::uint8_t >; - - static constexpr bool allow_bulk = true; - static constexpr std::size_t fixed_size = 1; - - template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in ) noexcept( noexcept( in.empty() ) ) - { - static_assert( sizeof( typename ParseInput::data_t ) == 1 ); - - if( in.empty() ) { - return { 0, 0 }; - } - return { std::uint8_t( std::uint8_t( *in.current() ) & M ), 1 }; - } - }; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/pegtl/internal/peek_masked.hpp b/include/tao/pegtl/internal/peek_masked.hpp new file mode 100644 index 000000000..15f9c19da --- /dev/null +++ b/include/tao/pegtl/internal/peek_masked.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_PEEK_MASKED_HPP +#define TAO_PEGTL_INTERNAL_PEEK_MASKED_HPP + +#include +#include + +#include "../config.hpp" + +#include "data_and_size.hpp" +#include "endian.hpp" +#include "integer_size.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename Data, Data Mask, typename Endian = identity_endian > + struct peek_masked + { + using data_t = Data; + using pair_t = data_and_size< data_t >; + + static constexpr bool allow_bulk = true; + static constexpr std::size_t fixed_size = sizeof( data_t ); + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( sizeof( data_t ) ) ) ) + { + const std::size_t s = integer_size< data_t >( in.current() ); + + if( in.size( s + offset ) >= ( s + offset ) ) { + const data_t t = Endian::template get< data_t >( in.current( offset ) ); + return pair_t( Mask & t, s ); + } + return pair_t(); + } + }; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/peek_member.hpp b/include/tao/pegtl/internal/peek_member.hpp new file mode 100644 index 000000000..c72df8348 --- /dev/null +++ b/include/tao/pegtl/internal/peek_member.hpp @@ -0,0 +1,117 @@ +// Copyright (c) 2022-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_PEEK_MEMBER_HPP +#define TAO_PEGTL_INTERNAL_PEEK_MEMBER_HPP + +#include +#include + +#include "../config.hpp" + +#include "data_and_size.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename T, T, typename = void > + struct peek_member_impl; + + // For data members of type 'T' or 'const T'. + + template< typename C, typename T, T C::*P > + struct peek_member_impl< T C::*, P, std::enable_if_t< std::is_member_object_pointer_v< T C::* > > > + { + using data_t = std::decay_t< T >; + using pair_t = data_and_size< data_t, void >; + + static constexpr bool allow_bulk = true; + static constexpr std::size_t fixed_size = 1; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 1 ) ) ) + { + return data_and_size( ( in.size( offset + 1 ) >= ( offset + 1 ) ) ? &( in.current( offset )->*P ) : nullptr ); + } + }; + + // For data members of type 'T*' or 'const T*'. + + template< typename C, typename T, T* C::*P > + struct peek_member_impl< T* C::*, P, std::enable_if_t< std::is_member_object_pointer_v< T* C::* > > > + { + using data_t = std::decay_t< T >; + using pair_t = data_and_size< data_t, void >; + + static constexpr bool allow_bulk = true; + static constexpr std::size_t fixed_size = 1; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 1 ) ) ) + { + return data_and_size( ( in.size( offset + 1 ) >= ( offset + 1 ) ) ? in.current( offset )->*P : nullptr ); + } + }; + + // For data members of type 'T* const' or 'const T* const'. + + template< typename C, typename T, T* const C::* const P > + struct peek_member_impl< T* const C::*, P, std::enable_if_t< std::is_member_object_pointer_v< T* const C::* > > > + { + using data_t = std::decay_t< T >; + using pair_t = data_and_size< data_t, void >; + + static constexpr bool allow_bulk = true; + static constexpr std::size_t fixed_size = 1; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 1 ) ) ) + { + return data_and_size( ( in.size( offset + 1 ) >= ( offset + 1 ) ) ? in.current( offset )->*P : nullptr ); + } + }; + + // For global getter functions that return a T or const T&. + + template< bool N, typename C, typename T, T ( *P )( const C& ) noexcept( N ) > + struct peek_member_impl< T ( * )( const C& ) noexcept( N ), P > + { + using data_t = std::decay_t< T >; + using pair_t = data_and_size< data_t, std::uint8_t >; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( N && noexcept( in.size( 1 ) ) ) + { + if( in.size( offset + 1 ) >= ( offset + 1 ) ) { + return pair_t( P( *in.current( offset ) ), 1 ); + } + return pair_t(); + } + }; + + // For member getter functions that return a T or const T&. + + template< bool N, typename C, typename T, T ( C::*P )() const noexcept( N ) > + struct peek_member_impl< T ( C::* )() const noexcept( N ), P > + { + using data_t = std::decay_t< T >; + using pair_t = data_and_size< data_t, std::uint8_t >; + + template< typename ParseInput > + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( N && noexcept( in.size( 1 ) ) ) + { + if( in.size( offset + 1 ) >= ( offset + 1 ) ) { + return pair_t( ( in.current( offset )->*P )(), 1 ); + } + return pair_t(); + } + }; + + template< auto M > + struct peek_member + : peek_member_impl< decltype( M ), M > + {}; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/peek_utf16.hpp b/include/tao/pegtl/internal/peek_utf16.hpp index ffab67dc2..26918fdb0 100644 --- a/include/tao/pegtl/internal/peek_utf16.hpp +++ b/include/tao/pegtl/internal/peek_utf16.hpp @@ -9,9 +9,10 @@ #include "../config.hpp" -#include "endian.hpp" #include "data_and_size.hpp" -#include "peek_endian.hpp" +#include "endian.hpp" +#include "integer_size.hpp" +#include "utility.hpp" namespace TAO_PEGTL_NAMESPACE::internal { @@ -21,22 +22,24 @@ namespace TAO_PEGTL_NAMESPACE::internal using data_t = char32_t; using pair_t = data_and_size< char32_t >; - static constexpr std::size_t fixed_size = 0; - - static_assert( sizeof( char16_t ) == 2 ); - static_assert( sizeof( char32_t ) == 4 ); + static constexpr std::size_t allow_bulk = false; template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 42 ) ) ) + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 2 ) ) ) { - if( const auto r = peek_endian< char16_t, Endian >::peek( in, offset ) ) { - if( ( r.data() < 0xd800 ) || ( r.data() > 0xdfff ) ) { - return pair_t( r.data(), r.size() ); + const std::size_t s = integer_size< char16_t >( in.current() ); + const std::size_t size = in.size( s + s + offset ); + + if( size >= ( s + offset ) ) { + const char16_t t = Endian::template get< char16_t >( in.current( offset ) ); + if( !is_utf16_surrogate( t ) ) { + return pair_t( t, s ); } - if( r.data() < 0xdc00 ) { - if( const auto s = peek_endian< char16_t, Endian >::peek( in, r.size() + offset ) ) { - if( ( s.data() >= 0xdc00 ) && ( s.data() <= 0xdfff ) ) { - return pair_t( ( ( char32_t( r.data() & 0x03ff ) << 10 ) | char32_t( s.data() & 0x03ff ) ) + 0x10000, std::uint8_t( r.size() + s.size() ) ); + if( is_utf16_high_surrogate( t ) ) { + if( size >= ( s + s + offset ) ) { + const char16_t u = Endian::template get< char16_t >( in.current( s + offset ) ); + if( is_utf16_low_surrogate( u ) ) { + return pair_t( utf16_surrogate_compose( t, u ), s + s ); } } } diff --git a/include/tao/pegtl/internal/peek_utf32.hpp b/include/tao/pegtl/internal/peek_utf32.hpp index 981512b6b..46ec20a2a 100644 --- a/include/tao/pegtl/internal/peek_utf32.hpp +++ b/include/tao/pegtl/internal/peek_utf32.hpp @@ -9,9 +9,10 @@ #include "../config.hpp" -#include "endian.hpp" #include "data_and_size.hpp" -#include "peek_endian.hpp" +#include "endian.hpp" +#include "integer_size.hpp" +#include "utility.hpp" namespace TAO_PEGTL_NAMESPACE::internal { @@ -21,18 +22,19 @@ namespace TAO_PEGTL_NAMESPACE::internal using data_t = char32_t; using pair_t = data_and_size< char32_t >; - static constexpr bool allow_bulk = true; + static constexpr bool allow_bulk = false; static constexpr std::size_t fixed_size = 4; - static_assert( sizeof( char32_t ) == 4 ); - template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 42 ) ) ) + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.size( 4 ) ) ) { - const pair_t r = peek_endian< char32_t, Endian >::peek( in, offset ); + const std::size_t s = integer_size< char32_t >( in.current() ); - if( ( r.data() <= 0x10ffff ) && !( ( r.data() >= 0xd800 ) && ( r.data() <= 0xdfff ) ) ) { - return r; + if( in.size( s + offset ) >= ( s + offset ) ) { + const char32_t t = Endian::template get< char32_t >( in.current( offset ) ); + if( is_utf32_codepoint( t ) ) { + return pair_t( t, s ); + } } return pair_t(); } diff --git a/include/tao/pegtl/internal/peek_utf8.hpp b/include/tao/pegtl/internal/peek_utf8.hpp index 454b53cb3..5d2ccc077 100644 --- a/include/tao/pegtl/internal/peek_utf8.hpp +++ b/include/tao/pegtl/internal/peek_utf8.hpp @@ -10,38 +10,37 @@ #include "../config.hpp" #include "data_and_size.hpp" +#include "integer_adapt.hpp" namespace TAO_PEGTL_NAMESPACE::internal { struct peek_utf8 { using data_t = char32_t; - using pair_t = data_and_size< char32_t, std::uint8_t >; + using pair_t = data_and_size< char32_t >; static constexpr bool allow_bulk = false; template< typename ParseInput > - [[nodiscard]] static pair_t peek( ParseInput& in ) noexcept( noexcept( in.empty() ) ) + [[nodiscard]] static pair_t peek( ParseInput& in, const std::size_t offset = 0 ) noexcept( noexcept( in.empty() ) ) { - static_assert( sizeof( decltype( *in.current() ) ) == 1 ); - - if( in.empty() ) { - return pair_t(); - } - const char32_t c0 = std::uint8_t( *in.current() ); - if( ( c0 & 0x80 ) == 0 ) { - return pair_t( c0, 1 ); + if( in.size( offset + 1 ) >= ( offset + 1 ) ) { + const char32_t c0 = integer_adapt< std::uint8_t >( in.current( offset ) ); + if( ( c0 & 0x80 ) == 0 ) { + return pair_t( c0, 1 ); + } + return peek_impl( in, c0, offset ); } - return peek_impl( in, c0 ); + return pair_t(); } private: template< typename ParseInput > - [[nodiscard]] static pair_t peek_impl( ParseInput& in, char32_t c0 ) noexcept( noexcept( in.size( 42 ) ) ) + [[nodiscard]] static pair_t peek_impl( ParseInput& in, char32_t c0, const std::size_t offset ) noexcept( noexcept( in.size( 42 ) ) ) { if( ( c0 & 0xE0 ) == 0xC0 ) { - if( in.size( 2 ) >= 2 ) { - const char32_t c1 = std::uint8_t( *in.current( 1 ) ); + if( in.size( offset + 2 ) >= ( offset + 2 ) ) { + const char32_t c1 = integer_adapt< std::uint8_t >( in.current( 1 + offset ) ); if( ( c1 & 0xC0 ) == 0x80 ) { c0 &= 0x1F; c0 <<= 6; @@ -53,9 +52,9 @@ namespace TAO_PEGTL_NAMESPACE::internal } } else if( ( c0 & 0xF0 ) == 0xE0 ) { - if( in.size( 3 ) >= 3 ) { - const char32_t c1 = std::uint8_t( *in.current( 1 ) ); - const char32_t c2 = std::uint8_t( *in.current( 2 ) ); + if( in.size( offset + 3 ) >= ( offset + 3 ) ) { + const char32_t c1 = integer_adapt< std::uint8_t >( in.current( 1 + offset ) ); + const char32_t c2 = integer_adapt< std::uint8_t >( in.current( 2 + offset ) ); if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) ) { c0 &= 0x0F; c0 <<= 6; @@ -69,10 +68,10 @@ namespace TAO_PEGTL_NAMESPACE::internal } } else if( ( c0 & 0xF8 ) == 0xF0 ) { - if( in.size( 4 ) >= 4 ) { - const char32_t c1 = std::uint8_t( *in.current( 1 ) ); - const char32_t c2 = std::uint8_t( *in.current( 2 ) ); - const char32_t c3 = std::uint8_t( *in.current( 3 ) ); + if( in.size( offset + 4 ) >= ( offset + 4 ) ) { + const char32_t c1 = integer_adapt< std::uint8_t >( in.current( 1 + offset ) ); + const char32_t c2 = integer_adapt< std::uint8_t >( in.current( 2 + offset ) ); + const char32_t c3 = integer_adapt< std::uint8_t >( in.current( 3 + offset ) ); if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) && ( ( c3 & 0xC0 ) == 0x80 ) ) { c0 &= 0x07; c0 <<= 6; diff --git a/include/tao/pegtl/internal/peeks.hpp b/include/tao/pegtl/internal/peeks.hpp new file mode 100644 index 000000000..4cb03c8d6 --- /dev/null +++ b/include/tao/pegtl/internal/peeks.hpp @@ -0,0 +1,64 @@ +// Copyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_PEEKS_HPP +#define TAO_PEGTL_INTERNAL_PEEKS_HPP + +#include +#include + +#include "../config.hpp" + +#include "peek_direct.hpp" +#include "peek_endian.hpp" +#include "peek_masked.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + using peek_char = peek_direct< char >; + using peek_byte = peek_direct< std::byte >; + + // using peek_char8 = peek_direct< char8_t >; // C++20 + using peek_char16 = peek_direct< char16_t >; + using peek_char32 = peek_direct< char32_t >; + + using peek_int8 = peek_direct< std::int8_t >; + using peek_uint8 = peek_direct< std::uint8_t >; + + template< std::uint8_t Mask > + using peek_mask_uint8 = peek_masked< std::uint8_t, Mask >; + + using peek_int16_be = peek_endian< std::int16_t, big_endian >; + using peek_int32_be = peek_endian< std::int32_t, big_endian >; + using peek_int64_be = peek_endian< std::int64_t, big_endian >; + + using peek_int16_le = peek_endian< std::int16_t, little_endian >; + using peek_int32_le = peek_endian< std::int32_t, little_endian >; + using peek_int64_le = peek_endian< std::int64_t, little_endian >; + + using peek_uint16_be = peek_endian< std::uint16_t, big_endian >; + using peek_uint32_be = peek_endian< std::uint32_t, big_endian >; + using peek_uint64_be = peek_endian< std::uint64_t, big_endian >; + + using peek_uint16_le = peek_endian< std::uint16_t, little_endian >; + using peek_uint32_le = peek_endian< std::uint32_t, little_endian >; + using peek_uint64_le = peek_endian< std::uint64_t, little_endian >; + + template< std::uint16_t Mask > + using peek_mask_uint16_be = peek_masked< std::uint16_t, Mask, big_endian >; + template< std::uint32_t Mask > + using peek_mask_uint32_be = peek_masked< std::uint32_t, Mask, big_endian >; + template< std::uint64_t Mask > + using peek_mask_uint64_be = peek_masked< std::uint64_t, Mask, big_endian >; + + template< std::uint16_t Mask > + using peek_mask_uint16_le = peek_masked< std::uint16_t, Mask, little_endian >; + template< std::uint32_t Mask > + using peek_mask_uint32_le = peek_masked< std::uint32_t, Mask, little_endian >; + template< std::uint64_t Mask > + using peek_mask_uint64_le = peek_masked< std::uint64_t, Mask, little_endian >; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/rules.hpp b/include/tao/pegtl/internal/rules.hpp index 59fba1d8f..56009d742 100644 --- a/include/tao/pegtl/internal/rules.hpp +++ b/include/tao/pegtl/internal/rules.hpp @@ -12,6 +12,7 @@ #include "at.hpp" #include "bof.hpp" #include "bol.hpp" +#include "consume.hpp" #include "control.hpp" #include "disable.hpp" #include "enable.hpp" @@ -21,6 +22,7 @@ #include "eolf.hpp" #include "everything.hpp" #include "failure.hpp" +#include "function.hpp" #include "identifier.hpp" #include "if_apply.hpp" #include "if_then_else.hpp" diff --git a/include/tao/pegtl/internal/text_eol_bump.hpp b/include/tao/pegtl/internal/text_eol_bump.hpp index 628ba45dc..d5cd6a01f 100644 --- a/include/tao/pegtl/internal/text_eol_bump.hpp +++ b/include/tao/pegtl/internal/text_eol_bump.hpp @@ -15,7 +15,9 @@ namespace TAO_PEGTL_NAMESPACE::internal template< typename Eol, typename Rule, typename Data, typename Position > void text_eol_bump( Position& pos, const Data* data, const std::size_t count ) { - bump_traits< Eol, Rule >::bump( pos, data, count ); + using eol_rule = typename Eol::rule_t; + using rule_rule = typename Rule::rule_t; + bump_traits< eol_rule, rule_rule >::bump( pos, data, count ); } } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/include/tao/pegtl/internal/text_eol_scan.hpp b/include/tao/pegtl/internal/text_eol_scan.hpp index 314a47d49..b06d80c08 100644 --- a/include/tao/pegtl/internal/text_eol_scan.hpp +++ b/include/tao/pegtl/internal/text_eol_scan.hpp @@ -16,7 +16,7 @@ namespace TAO_PEGTL_NAMESPACE::internal void text_eol_scan( Position& pos, const Data* data, const Data* dend ) { scan_input< Data > in( data, dend ); - scan_traits< typename Eol::rule_t >::scan( in, pos ); + scan_traits< Eol >::scan( in, pos ); pos.count += dend - data; } diff --git a/include/tao/pegtl/internal/text_eol_tags.hpp b/include/tao/pegtl/internal/text_eol_tags.hpp index 9b1d46273..9fb2098d1 100644 --- a/include/tao/pegtl/internal/text_eol_tags.hpp +++ b/include/tao/pegtl/internal/text_eol_tags.hpp @@ -10,13 +10,19 @@ namespace TAO_PEGTL_NAMESPACE::internal { struct eol_exclude_tag - {}; + { + using rule_t = eol_exclude_tag; + }; struct eol_matched_tag - {}; + { + using rule_t = eol_matched_tag; + }; struct eol_unknown_tag - {}; + { + using rule_t = eol_unknown_tag; + }; } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/include/tao/pegtl/internal/text_input.hpp b/include/tao/pegtl/internal/text_input.hpp index 15439e0e0..f608782a8 100644 --- a/include/tao/pegtl/internal/text_input.hpp +++ b/include/tao/pegtl/internal/text_input.hpp @@ -8,10 +8,7 @@ #include #include -#include "../apply_mode.hpp" #include "../config.hpp" -#include "../normal.hpp" -#include "../nothing.hpp" #include "../pointer_position.hpp" #include "../rewind_mode.hpp" #include "../text_position.hpp" @@ -27,7 +24,7 @@ namespace TAO_PEGTL_NAMESPACE::internal { public: using base_t = input_with_lines< Eol, Input >; - using data_t = char; + using data_t = typename Input::data_t; using error_position_t = text_position; using rewind_position_t = text_position; diff --git a/include/tao/pegtl/internal/text_input_with_source.hpp b/include/tao/pegtl/internal/text_input_with_source.hpp index d0e3f5fad..ad93af79d 100644 --- a/include/tao/pegtl/internal/text_input_with_source.hpp +++ b/include/tao/pegtl/internal/text_input_with_source.hpp @@ -13,6 +13,7 @@ #include "../text_position.hpp" #include "input_with_lines.hpp" +#include "text_eol_bump.hpp" namespace TAO_PEGTL_NAMESPACE::internal { diff --git a/include/tao/pegtl/internal/type_traits.hpp b/include/tao/pegtl/internal/type_traits.hpp new file mode 100644 index 000000000..fd386513d --- /dev/null +++ b/include/tao/pegtl/internal/type_traits.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_TYPE_TRAITS_HPP +#define TAO_PEGTL_INTERNAL_TYPE_TRAITS_HPP + +#include +#include + +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< unsigned Size > + struct integer_traits; + + template<> + struct integer_traits< 1 > + { + using signed_t = std::int8_t; + using unsigned_t = std::uint8_t; + }; + + template<> + struct integer_traits< 2 > + { + using signed_t = std::int16_t; + using unsigned_t = std::uint16_t; + }; + + template<> + struct integer_traits< 4 > + { + using signed_t = std::int32_t; + using unsigned_t = std::uint32_t; + }; + + template<> + struct integer_traits< 8 > + { + using signed_t = std::int64_t; + using unsigned_t = std::uint64_t; + }; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/internal/utility.hpp b/include/tao/pegtl/internal/utility.hpp new file mode 100644 index 000000000..b739e1636 --- /dev/null +++ b/include/tao/pegtl/internal/utility.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_INTERNAL_UTILITY_HPP +#define TAO_PEGTL_INTERNAL_UTILITY_HPP + +#include +#include + +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + [[nodiscard]] constexpr bool is_integer_fraction( const std::size_t n, const std::size_t d ) noexcept + { + return ( n / d ) * d == n; + } + + template< typename T > + [[nodiscard]] constexpr bool is_ascii_value( const T t ) noexcept + { + if constexpr( std::is_unsigned_v< T > ) { + return t <= 127; + } + else if constexpr( sizeof( T ) == 1 ) { + return 0 <= t; + } + else { + return ( 0 <= t ) && ( t <= 127 ); + } + } + + [[nodiscard]] constexpr bool is_utf16_surrogate( const char32_t t ) noexcept + { + return ( 0xd800 <= t ) && ( t <= 0xdfff ); + } + + [[nodiscard]] constexpr bool is_utf16_high_surrogate( const char32_t t ) noexcept + { + return ( 0xd800 <= t ) && ( t <= 0xdbff ); + } + + [[nodiscard]] constexpr bool is_utf16_low_surrogate( const char32_t t ) noexcept + { + return ( 0xdc00 <= t ) && ( t <= 0xdfff ); + } + + [[nodiscard]] constexpr char32_t utf16_surrogate_compose( const char16_t high, const char16_t low ) noexcept + { + return ( ( char32_t( high & 0x03ff ) << 10 ) | char32_t( low & 0x03ff ) ) + 0x10000; + } + + [[nodiscard]] bool is_utf32_codepoint( const char32_t t ) noexcept + { + return ( t <= 0x10ffff ) && ( !is_utf16_surrogate( t ) ); + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/pegtl/rules.hpp b/include/tao/pegtl/rules.hpp index 11845155f..253759047 100644 --- a/include/tao/pegtl/rules.hpp +++ b/include/tao/pegtl/rules.hpp @@ -22,6 +22,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename... Rules > struct at : internal::at< Rules... > {}; struct bof : internal::bof {}; struct bol : internal::bol {}; + template< std::size_t Count > struct consume : internal::consume< Count > {}; template< template< typename... > class Control, typename... Rules > struct control : internal::control< Control, Rules... > {}; template< typename... Rules > struct disable : internal::disable< Rules... > {}; template< typename... Rules > struct enable : internal::enable< Rules... > {}; @@ -30,6 +31,7 @@ namespace TAO_PEGTL_NAMESPACE struct eolf : internal::eolf {}; struct everything : internal::everything< std::size_t > {}; struct failure : internal::failure {}; + template< auto Function, typename Peek = void > struct function : internal::function< decltype( Function ), Function, Peek > {}; template< typename Rule, typename... Actions > struct if_apply : internal::if_apply< Rule, Actions... > {}; template< typename Cond, typename Then, typename Else > struct if_then_else : internal::if_then_else< Cond, Then, Else > {}; template< typename Rule > struct invert : invert_traits< typename Rule::rule_t >::rule_t {}; diff --git a/include/tao/pegtl/uint16.hpp b/include/tao/pegtl/uint16.hpp index 8924a6840..c39ee65b5 100644 --- a/include/tao/pegtl/uint16.hpp +++ b/include/tao/pegtl/uint16.hpp @@ -7,8 +7,7 @@ #include "config.hpp" -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_endian.hpp" +#include "internal/peeks.hpp" #include "internal/result_on_found.hpp" #include "internal/rules.hpp" diff --git a/include/tao/pegtl/uint32.hpp b/include/tao/pegtl/uint32.hpp index 7f0c20d85..ca07fb5d9 100644 --- a/include/tao/pegtl/uint32.hpp +++ b/include/tao/pegtl/uint32.hpp @@ -7,8 +7,7 @@ #include "config.hpp" -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_endian.hpp" +#include "internal/peeks.hpp" #include "internal/result_on_found.hpp" #include "internal/rules.hpp" diff --git a/include/tao/pegtl/uint64.hpp b/include/tao/pegtl/uint64.hpp index b8c996579..08c4f5664 100644 --- a/include/tao/pegtl/uint64.hpp +++ b/include/tao/pegtl/uint64.hpp @@ -7,8 +7,7 @@ #include "config.hpp" -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_endian.hpp" +#include "internal/peeks.hpp" #include "internal/result_on_found.hpp" #include "internal/rules.hpp" diff --git a/include/tao/pegtl/uint8.hpp b/include/tao/pegtl/uint8.hpp index 1bc59872a..7df305e90 100644 --- a/include/tao/pegtl/uint8.hpp +++ b/include/tao/pegtl/uint8.hpp @@ -7,9 +7,8 @@ #include "config.hpp" +#include "internal/peeks.hpp" #include "internal/result_on_found.hpp" -#include "internal/peek_direct.hpp" -#include "internal/peek_mask_uint8.hpp" #include "internal/rules.hpp" namespace TAO_PEGTL_NAMESPACE::uint8 diff --git a/src/test/pegtl/actions_1.cpp b/src/test/pegtl/action_apply_1.cpp similarity index 100% rename from src/test/pegtl/actions_1.cpp rename to src/test/pegtl/action_apply_1.cpp diff --git a/src/test/pegtl/actions_2.cpp b/src/test/pegtl/action_apply_2.cpp similarity index 100% rename from src/test/pegtl/actions_2.cpp rename to src/test/pegtl/action_apply_2.cpp diff --git a/src/test/pegtl/actions_3.cpp b/src/test/pegtl/action_apply_3.cpp similarity index 100% rename from src/test/pegtl/actions_3.cpp rename to src/test/pegtl/action_apply_3.cpp diff --git a/src/test/pegtl/contrib_function.cpp b/src/test/pegtl/contrib_function.cpp deleted file mode 100644 index 9c1769711..000000000 --- a/src/test/pegtl/contrib_function.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2020-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#include "test.hpp" -#include "test_inputs.hpp" - -#include -#include - -namespace TAO_PEGTL_NAMESPACE -{ - bool call1 = false; - - [[nodiscard]] bool func1( test::text_input< ascii::lf >& /*unused*/, int /*unused*/, char*& /*unused*/, const double& /*unused*/ ) - { - call1 = true; - return true; - } - - struct rule1 - : TAO_PEGTL_NAMESPACE::function< func1 > - {}; - - void unit_test() - { - int i = 42; - char c = 'a'; - double d = 42.0; - test::text_input< ascii::lf > in( "foo" ); - TAO_PEGTL_TEST_ASSERT( parse< rule1 >( in, i, &c, d ) ); - TAO_PEGTL_TEST_ASSERT( call1 ); - } - -} // namespace TAO_PEGTL_NAMESPACE - -#include "main.hpp" diff --git a/src/test/pegtl/contrib_json.cpp b/src/test/pegtl/contrib_json.cpp index c87ba2f45..accfc1cff 100644 --- a/src/test/pegtl/contrib_json.cpp +++ b/src/test/pegtl/contrib_json.cpp @@ -16,10 +16,10 @@ namespace TAO_PEGTL_NAMESPACE [[nodiscard]] bool json_pass( const std::filesystem::path& path ) { - test::file_input< ascii::lf_crlf > in( path ); + test::file_input< ascii::lf > in( path ); const auto s = in.string(); - test::text_input< ascii::lf_crlf > ti( s ); - test::lazy_input< ascii::lf_crlf > li( s ); + test::text_input< ascii::lf > ti( s ); + test::lazy_input< ascii::lf > li( s ); const auto f = failed; TAO_PEGTL_TEST_ASSERT( in.size() == ti.size() ); TAO_PEGTL_TEST_ASSERT( in.size() == li.size() ); @@ -36,10 +36,10 @@ namespace TAO_PEGTL_NAMESPACE [[nodiscard]] bool json_fail( const std::filesystem::path& path ) { - test::file_input< ascii::lf_crlf > in( path ); + test::file_input< ascii::lf > in( path ); const auto s = in.string(); - test::text_input< ascii::lf_crlf > ti( s ); - test::lazy_input< ascii::lf_crlf > li( s ); + test::text_input< ascii::lf > ti( s ); + test::lazy_input< ascii::lf > li( s ); const auto f = failed; TAO_PEGTL_TEST_ASSERT( in.size() == ti.size() ); TAO_PEGTL_TEST_ASSERT( in.size() == li.size() ); @@ -85,40 +85,40 @@ namespace TAO_PEGTL_NAMESPACE verify_rule< GRAMMAR >( __LINE__, __FILE__, "[\"\xF4\x8F\xBF\xBF\"]", result_type::success, 0 ); // largest allowed codepoint U+10FFFF verify_rule< GRAMMAR >( __LINE__, __FILE__, "[\"\U0010FFFF\"]", result_type::success, 0 ); // largest allowed codepoint U+10FFFF - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " [", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " ]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[ ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "] ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " [ ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( " ] ", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\a\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\c\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\d\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\e\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\v\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\'\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\b\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\f\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\n\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\r\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\t\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\\\\\\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\\u12\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\xFF\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\xF4\x90\x80\x80\"]", "" ) ) ); - TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf_crlf >( "[\"\xF7\xBF\xBF\xBF\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " [", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " ]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[ ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "] ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " [ ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( " ] ", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\a\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\c\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\d\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\e\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\v\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\'\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\b\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\f\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\n\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\r\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\t\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\\\\\\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\\u12\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\xFF\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\xF4\x90\x80\x80\"]", "" ) ) ); + TAO_PEGTL_TEST_ASSERT( !parse< GRAMMAR >( test::text_input< ascii::lf >( "[\"\xF7\xBF\xBF\xBF\"]", "" ) ) ); TAO_PEGTL_TEST_ASSERT( json_pass( "src/test/pegtl/data/pass1.json" ) ); TAO_PEGTL_TEST_ASSERT( json_pass( "src/test/pegtl/data/pass2.json" ) ); TAO_PEGTL_TEST_ASSERT( json_pass( "src/test/pegtl/data/pass3.json" ) ); - TAO_PEGTL_TEST_ASSERT( parse< GRAMMAR >( test::file_input< ascii::lf_crlf >( "src/test/pegtl/data/blns.json" ) ) ); + TAO_PEGTL_TEST_ASSERT( parse< GRAMMAR >( test::file_input< ascii::lf >( "src/test/pegtl/data/blns.json" ) ) ); // TAO_PEGTL_TEST_ASSERT( json_fail( "src/test/pegtl/data/fail1.json" ) ); // disabled as it is valid now TAO_PEGTL_TEST_ASSERT( json_fail( "src/test/pegtl/data/fail2.json" ) ); diff --git a/src/test/pegtl/contrib_raw_string.cpp b/src/test/pegtl/contrib_raw_string.cpp index 66f86f2f9..9dce2b4a4 100644 --- a/src/test/pegtl/contrib_raw_string.cpp +++ b/src/test/pegtl/contrib_raw_string.cpp @@ -56,20 +56,22 @@ namespace TAO_PEGTL_NAMESPACE {}; template< typename Rule, template< typename > class Action, unsigned M, unsigned N > - void verify_data( const std::size_t line, const char* file, const char ( &m )[ M ], const char ( &n )[ N ] ) + void verify_data( const std::size_t line, const char* file, const char ( &m )[ M ], const char ( &n )[ N ], const std::size_t count, const std::size_t dline, const std::size_t column ) { content.clear(); - test::text_input< ascii::lf_crlf > in( m, m + M - 1 ); + test::text_input< ascii::lf_crlf > in( m, m + M - 1 ); const auto r = parse< Rule, Action >( in ); if( ( !r ) || ( content != std::string_view( n, N - 1 ) ) ) { TAO_PEGTL_TEST_FAILED( "input data [ '" << m << "' ] expected success with [ '" << n << "' ] but got [ '" << content << "' ] result [ " << r << " ]" ); // LCOV_EXCL_LINE } + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), count, dline, column ) ); content.clear(); test::lazy_input< ascii::lf_crlf > in2( m, m + M - 1 ); const auto r2 = parse< Rule, Action >( in2 ); if( ( !r2 ) || ( content != std::string_view( n, N - 1 ) ) ) { TAO_PEGTL_TEST_FAILED( "input data [ '" << m << "' ] with tracking_mode::lazy expected success with [ '" << n << "' ] but got [ '" << content << "' ] result [ " << r2 << " ]" ); // LCOV_EXCL_LINE } + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), count, dline, column ) ); } template< typename Rule > @@ -88,19 +90,20 @@ namespace TAO_PEGTL_NAMESPACE verify_analyze< raw_string< 'a', 'b', 'c', star< star< any > > > >( __LINE__, __FILE__, true, true ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[[]]", "" ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[[foo]]", "foo" ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[foo]===]", "foo" ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\nfoo]===]", "foo" ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\r\nfoo]===]", "foo" ); - verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\0\0\0]===]", "\0\0\0" ); - - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[[]]", "" ); - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[[a1]]", "a1" ); - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[a1]===]", "a1" ); - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[\na1]===]", "a1" ); - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[\r\na1]===]", "a1" ); - verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[a0a1a2a3]===]", "a0a1a2a3" ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[[]]", "", 4, 1, 5 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[[foo]]", "foo", 7, 1, 8 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[foo]===]", "foo", 13, 1, 14 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\nfoo]===]", "foo", 14, 2, 9 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\r\nfoo]===]", "foo", 15, 2, 9 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[===[\0\0\0]===]", "\0\0\0", 13, 1, 14 ); + verify_data< rgrammar, raction >( __LINE__, __FILE__, "[=[\na\nb\nc\n]=]", "a\nb\nc\n", 13, 5, 4 ); + + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[[]]", "", 4, 1, 5 ); + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[[a1]]", "a1", 6, 1, 7 ); + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[a1]===]", "a1", 12, 1, 13 ); + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[\na1]===]", "a1", 13, 2, 8 ); + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[\r\na1]===]", "a1", 14, 2, 8 ); + verify_data< qgrammar, qaction >( __LINE__, __FILE__, "[===[a0a1a2a3]===]", "a0a1a2a3", 18, 1, 19 ); verify_fail< rgrammar >( __LINE__, __FILE__, "" ); verify_fail< rgrammar >( __LINE__, __FILE__, "[" ); diff --git a/src/test/pegtl/contrib_unescape.cpp b/src/test/pegtl/contrib_unescape.cpp index 8bf467f8f..d2f7560c3 100644 --- a/src/test/pegtl/contrib_unescape.cpp +++ b/src/test/pegtl/contrib_unescape.cpp @@ -36,14 +36,14 @@ namespace TAO_PEGTL_NAMESPACE { std::string s; test::text_input< ascii::lf > in( m ); - std::cerr << __LINE__ << " : " << m << std::endl; - std::cerr << __LINE__ << " : " << in.string_view() << std::endl; - std::cerr << __LINE__ << " : " << n << std::endl; + // std::cerr << __LINE__ << " : " << m << std::endl; + // std::cerr << __LINE__ << " : " << in.string_view() << std::endl; + // std::cerr << __LINE__ << " : " << n << std::endl; if( !parse< unstring, unaction >( in, s ) ) { - std::cerr << __LINE__ << " : " << s << std::endl; + // std::cerr << __LINE__ << " : " << s << std::endl; return false; // LCOV_EXCL_LINE } - std::cerr << __LINE__ << " : " << s << std::endl; + // std::cerr << __LINE__ << " : " << s << std::endl; return s == std::string( n, N - 1 ); } diff --git a/src/test/pegtl/internal_inputs_base.cpp b/src/test/pegtl/internal_base_inputs.cpp similarity index 100% rename from src/test/pegtl/internal_inputs_base.cpp rename to src/test/pegtl/internal_base_inputs.cpp diff --git a/src/test/pegtl/internal_endian.cpp b/src/test/pegtl/internal_endian.cpp index 7d7f31050..f15fae99e 100644 --- a/src/test/pegtl/internal_endian.cpp +++ b/src/test/pegtl/internal_endian.cpp @@ -10,68 +10,68 @@ namespace TAO_PEGTL_NAMESPACE { void unit_test() { - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); -#if defined( TAO_PEGTL_BIG_ENDIAN ) - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int8_t( 0x7a ) ) == std::int8_t( 0x7a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint8_t( 0x7a ) ) == std::uint8_t( 0x7a ) ); +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); -#elif defined( TAO_PEGTL_LITTLE_ENDIAN ) - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x7a39 ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int16_t( 0x7a39 ) ) == std::int16_t( 0x397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint16_t( 0x7a39 ) ) == std::uint16_t( 0x397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x7a391f2b ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int32_t( 0x7a391f2b ) ) == std::int32_t( 0x2b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint32_t( 0x7a391f2b ) ) == std::uint32_t( 0x2b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::native_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::other_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::little_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); - TAO_PEGTL_TEST_ASSERT( internal::big_endian::from( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::identity_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::byteswap_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::little_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x7a391f2b33445567 ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::int64_t( 0x7a391f2b33445567 ) ) == std::int64_t( 0x675544332b1f397a ) ); + TAO_PEGTL_TEST_ASSERT( internal::big_endian::get( std::uint64_t( 0x7a391f2b33445567 ) ) == std::uint64_t( 0x675544332b1f397a ) ); #else static_assert( false ); #endif diff --git a/src/test/pegtl/internal_inputs_lazy.cpp b/src/test/pegtl/internal_inputs_lazy.cpp deleted file mode 100644 index 1f4d49f9d..000000000 --- a/src/test/pegtl/internal_inputs_lazy.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2021-2023 Dr. Colin Hirsch and Daniel Frey -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) - -#include "test.hpp" - -#include -#include -#include - -#include "test_inputs.hpp" - -namespace TAO_PEGTL_NAMESPACE -{ - template< typename T > - [[nodiscard]] bool equal( const T& position, const std::size_t count, const std::size_t line, const std::size_t column ) noexcept - { - return ( position.count == count ) && ( position.line == line ) && ( position.column == column ); - } - - void test_01_lazy() - { - using input_1 = test::lazy_input< ascii::lf >; - { - input_1 in( "" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); - TAO_PEGTL_TEST_ASSERT( in.empty() ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - } { - input_1 in( " " ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( in.empty() ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 1, 1, 2 ) ); - } { - input_1 in( "\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( in.empty() ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 1, 2, 1 ) ); - } - using input_2 = test::lazy_input< ascii::cr_lf_crlf >; - { - input_2 in( "" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - } { - input_2 in( " " ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 1, 1, 2 ) ); - } { - input_2 in( "\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 1, 2, 1 ) ); - } { - input_2 in( "\r" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 1, 2, 1 ) ); - } { - input_2 in( "\r\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 2, 2, 1 ) ); - } { - input_2 in( "\n\r" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 2, 3, 1 ) ); - } { - input_2 in( " \n " ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); - TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 3, 2, 2 ) ); - } - } - - void unit_test() - { - test_01_lazy(); - } - -} // namespace TAO_PEGTL_NAMESPACE - -#include "main.hpp" diff --git a/src/test/pegtl/internal_lazy_inputs.cpp b/src/test/pegtl/internal_lazy_inputs.cpp new file mode 100644 index 000000000..a68a1f4b0 --- /dev/null +++ b/src/test/pegtl/internal_lazy_inputs.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2021-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" + +#include +#include +#include + +#include "test_inputs.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + void test_01_lazy() + { + using input_1 = test::lazy_input< ascii::lf >; + { + input_1 in( "" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + } { + input_1 in( " " ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 1, 1, 2 ) ); + } { + input_1 in( "\n" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 1, 2, 1 ) ); + } + using input_2 = test::lazy_input< ascii::cr_lf_crlf >; + { + input_2 in( "" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + } { + input_2 in( " " ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 1, 1, 2 ) ); + } { + input_2 in( "\n" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 1, 2, 1 ) ); + } { + input_2 in( "\r" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 1, 2, 1 ) ); + } { + input_2 in( "\r\n" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 2, 2, 1 ) ); + } { + input_2 in( "\n\r" ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 2, 3, 1 ) ); + } { + input_2 in( " \n " ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 3, 2, 2 ) ); + } + using input_3 = test::lazy_input< ascii::lf >; + { + input_3 in( " \n " ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< one< '\n' > >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 3, 2, 2 ) ); + } + } + + void unit_test() + { + test_01_lazy(); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/src/test/pegtl/internal_peek_member.cpp b/src/test/pegtl/internal_peek_member.cpp new file mode 100644 index 000000000..14d812b9c --- /dev/null +++ b/src/test/pegtl/internal_peek_member.cpp @@ -0,0 +1,147 @@ +// Copyright (c) 2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include "test.hpp" + +#include +#include +#include +#include + +namespace TAO_PEGTL_NAMESPACE +{ + static int the_integer = -2; + + struct token + { + explicit token( std::string&& s ) noexcept + : string( std::move( s ) ) + {} + + std::string string; + + int local1 = 12; + const int local2 = 23; + + int* global1 = &the_integer; + const int* global2 = &the_integer; + int* const global3 = &the_integer; + const int* const global4 = &the_integer; + + [[nodiscard]] int method1() const noexcept + { + return 503; + } + + const int method2_int = 102; + + [[nodiscard]] const int& method2() const noexcept + { + return method2_int; + } + + int other = 900; + }; + + [[nodiscard]] int get_other1( const token& t ) noexcept + { + return t.other; + } + + [[nodiscard]] const int& get_other2( const token& t ) noexcept + { + return t.other; + } + + using tokens = std::vector< token >; + + using test_input = internal::input_with_fakes< internal::copy_input< tokens > >; + + static int test_integer = -1; + + [[nodiscard]] bool func1( const int i ) noexcept + { + test_integer = i; + return true; + } + + void unit_test() + { + tokens ts; + ts.emplace_back( "0" ); + ts.emplace_back( "token" ); + ts.emplace_back( "something" ); + { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::local1 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 12 ); + } { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::local2 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 23 ); + } { + the_integer = 42; + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::global1 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 42 ); + } { + the_integer = -120; + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::global2 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == -120 ); + } { + the_integer = 0; + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::global3 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 0 ); + } { + the_integer = 65536; + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::global4 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 65536 ); + } { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::method1 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 503 ); + } { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &token::method2 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 102 ); + } { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &get_other1 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 900 ); + } { + test_integer = -1; + test_input in( ts ); + const auto b = parse< function< func1, internal::peek_member< &get_other2 > > >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( test_integer == 900 ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/src/test/pegtl/internal_inputs_text.cpp b/src/test/pegtl/internal_text_inputs.cpp similarity index 60% rename from src/test/pegtl/internal_inputs_text.cpp rename to src/test/pegtl/internal_text_inputs.cpp index aa56a4712..6597a450c 100644 --- a/src/test/pegtl/internal_inputs_text.cpp +++ b/src/test/pegtl/internal_text_inputs.cpp @@ -12,92 +12,94 @@ namespace TAO_PEGTL_NAMESPACE { - template< typename T > - [[nodiscard]] bool equal( const T& position, const std::size_t count, const std::size_t line, const std::size_t column ) noexcept - { - return ( position.count == count ) && ( position.line == line ) && ( position.column == column ); - } - void test_01_text() { using input_1 = test::text_input< ascii::lf >; { input_1 in( "" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_1 in( " " ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 1, 1, 2 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 1, 1, 2 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_1 in( "\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - std::cerr << __LINE__ << " " << in.direct_position() << std::endl; - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 1, 2, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 1, 2, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } using input_2 = test::text_input< ascii::cr_lf_crlf >; { input_2 in( "" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eof >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( " " ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 1, 1, 2 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 1, 1, 2 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( "\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 1, 2, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 1, 2, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( "\r" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 1, 2, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 1, 2, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( "\r\n" ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - TAO_PEGTL_TEST_ASSERT( equal( in.direct_position(), 2, 2, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.direct_position(), 2, 2, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( "\n\r" ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); - std::cerr << __LINE__ << " " << in.direct_position() << std::endl; - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 2, 3, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 2, 3, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } { input_2 in( " \n " ); - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); TAO_PEGTL_TEST_ASSERT( parse< eol >( in ) ); TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); - std::cerr << __LINE__ << " " << in.direct_position() << std::endl; - TAO_PEGTL_TEST_ASSERT( equal( in.current_position(), 3, 2, 2 ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 3, 2, 2 ) ); + TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); + } + using input_3 = test::text_input< ascii::lf >; + { + input_3 in( " \n " ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 0, 1, 1 ) ); + TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< one< '\n' > >( in ) ); + TAO_PEGTL_TEST_ASSERT( parse< blank >( in ) ); + TAO_PEGTL_TEST_ASSERT( test::equal( in.current_position(), 3, 2, 2 ) ); TAO_PEGTL_TEST_ASSERT( in.direct_position() == in.current_position() ); } } diff --git a/src/test/pegtl/pegtl.cpp b/src/test/pegtl/pegtl.cpp index 0a07a52bc..3ca6c3714 100644 --- a/src/test/pegtl/pegtl.cpp +++ b/src/test/pegtl/pegtl.cpp @@ -9,7 +9,11 @@ namespace TAO_PEGTL_NAMESPACE { void unit_test() - {} + { + static_assert( sizeof( char ) == 1 ); + static_assert( sizeof( char16_t ) == 2 ); + static_assert( sizeof( char32_t ) == 4 ); + } } // namespace TAO_PEGTL_NAMESPACE diff --git a/src/test/pegtl/rule_function.cpp b/src/test/pegtl/rule_function.cpp new file mode 100644 index 000000000..6e2d31a1f --- /dev/null +++ b/src/test/pegtl/rule_function.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2020-2023 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "test_inputs.hpp" + +#include +#include +#include +#include + +namespace TAO_PEGTL_NAMESPACE +{ + static bool called = false; + + template< auto F, typename P = void > + void unit_test_1() + { + int i = 42; + char c = 'a'; + double d = 42.0; + called = false; + test::text_input< ascii::lf > in( "f" ); + TAO_PEGTL_TEST_ASSERT( parse< seq< function< F, P >, eof > >( in, i, &c, d ) ); + TAO_PEGTL_TEST_ASSERT( called ); + } + + [[nodiscard]] bool func1( test::text_input< ascii::lf >& in, int /*unused*/, char*& /*unused*/, const double& /*unused*/ ) + { + called = true; + in.consume< internal::eol_exclude_tag >( 1 ); + return true; + } + + [[nodiscard]] bool func1n( test::text_input< ascii::lf >& in, int /*unused*/, char*& /*unused*/, const double& /*unused*/ ) noexcept + { + called = true; + in.consume< internal::eol_exclude_tag >( 1 ); + return true; + } + + [[nodiscard]] bool func2( const char /*unused*/, int /*unused*/, char*& /*unused*/, const double& /*unused*/ ) + { + called = true; + return true; + } + + [[nodiscard]] bool func2n( const char /*unused*/, int /*unused*/, char*& /*unused*/, const double& /*unused*/ ) noexcept + { + called = true; + return true; + } + + [[nodiscard]] bool func3( const char /*unused*/ ) + { + called = true; + return true; + } + + [[nodiscard]] bool func3n( const char /*unused*/ ) noexcept + { + called = true; + return true; + } + + void unit_test() + { + unit_test_1< func1 >(); + unit_test_1< func2, internal::peek_char >(); + unit_test_1< func2, internal::peek_ascii >(); + unit_test_1< func2, internal::peek_current >(); + unit_test_1< func3, internal::peek_char >(); + unit_test_1< func3, internal::peek_ascii >(); + unit_test_1< func3, internal::peek_current >(); + unit_test_1< func1n >(); + unit_test_1< func2n, internal::peek_char >(); + unit_test_1< func2n, internal::peek_ascii >(); + unit_test_1< func2n, internal::peek_current >(); + unit_test_1< func3n, internal::peek_char >(); + unit_test_1< func3n, internal::peek_ascii >(); + unit_test_1< func3n, internal::peek_current >(); + // unit_test_1< decltype( TODO: An appropriate lambda as soon as we switch to C++20 ) ... + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/src/test/pegtl/test_inputs.hpp b/src/test/pegtl/test_inputs.hpp index 39224252b..7d9873fb9 100644 --- a/src/test/pegtl/test_inputs.hpp +++ b/src/test/pegtl/test_inputs.hpp @@ -5,6 +5,8 @@ #ifndef TAO_PEGTL_SRC_TEST_PEGTL_TEST_INPUTS_HPP #define TAO_PEGTL_SRC_TEST_PEGTL_TEST_INPUTS_HPP +#include + #include #include @@ -19,6 +21,12 @@ namespace TAO_PEGTL_NAMESPACE::test template< typename Eol > using file_input = internal::input_with_peeks< internal::input_with_fakes< internal::text_file_input_with_source< Eol > > >; + template< typename T > + [[nodiscard]] bool equal( const T& position, const std::size_t count, const std::size_t line, const std::size_t column ) noexcept + { + return ( position.count == count ) && ( position.line == line ) && ( position.column == column ); + } + } // namespace TAO_PEGTL_NAMESPACE::test #endif