diff -Nru tao-pegtl-2.7.0/CMakeLists.txt tao-pegtl-2.7.1/CMakeLists.txt --- tao-pegtl-2.7.0/CMakeLists.txt 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/CMakeLists.txt 2018-10-02 14:31:17.000000000 +0000 @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.3.0 FATAL_ERROR) -project (pegtl VERSION 2.7.0 LANGUAGES CXX) +project (pegtl VERSION 2.7.1 LANGUAGES CXX) # installation directories set (PEGTL_INSTALL_INCLUDE_DIR "include" CACHE STRING "The installation include directory") diff -Nru tao-pegtl-2.7.0/debian/changelog tao-pegtl-2.7.1/debian/changelog --- tao-pegtl-2.7.0/debian/changelog 2018-08-07 18:30:15.000000000 +0000 +++ tao-pegtl-2.7.1/debian/changelog 2018-10-02 14:32:14.000000000 +0000 @@ -1,3 +1,11 @@ +tao-pegtl (2.7.1-1) unstable; urgency=medium + + * Add a gitlab-ci.yml file + * New upstream version 2.7.1 + * Add missing Vcs-* fields (Closes: #908458) + + -- Birger Schacht Tue, 02 Oct 2018 16:32:14 +0200 + tao-pegtl (2.7.0-1) unstable; urgency=low * Initial release. Closes: #905853 diff -Nru tao-pegtl-2.7.0/debian/control tao-pegtl-2.7.1/debian/control --- tao-pegtl-2.7.0/debian/control 2018-08-07 18:30:15.000000000 +0000 +++ tao-pegtl-2.7.1/debian/control 2018-10-02 14:32:14.000000000 +0000 @@ -3,12 +3,15 @@ Priority: optional Maintainer: Birger Schacht Build-Depends: cmake, debhelper (>=11~) -Standards-Version: 4.2.0 +Standards-Version: 4.2.1 Homepage: https://github.com/taocpp/PEGTL +Vcs-Browser: https://salsa.debian.org/bisco-guest/tao-pegtl +Vcs-Git: https://salsa.debian.org/bisco-guest/tao-pegtl.git Package: tao-pegtl-dev Section: libdevel -Architecture: any +Architecture: all +Multi-Arch: foreign Depends: ${misc:Depends}, ${shlibs:Depends} Description: Parsing Expression Grammar Template Library The Parsing Expression Grammar Template Library (PEGTL) is a zero-dependency diff -Nru tao-pegtl-2.7.0/debian/gitlab-ci.yml tao-pegtl-2.7.1/debian/gitlab-ci.yml --- tao-pegtl-2.7.0/debian/gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/debian/gitlab-ci.yml 2018-10-02 14:32:14.000000000 +0000 @@ -0,0 +1,9 @@ +image: registry.gitlab.com/eighthave/ci-image-git-buildpackage:latest + +build: + artifacts: + paths: + - "*.deb" + expire_in: 1 day + script: + - gitlab-ci-git-buildpackage-all diff -Nru tao-pegtl-2.7.0/doc/Changelog.md tao-pegtl-2.7.1/doc/Changelog.md --- tao-pegtl-2.7.0/doc/Changelog.md 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/doc/Changelog.md 2018-10-02 14:31:17.000000000 +0000 @@ -1,5 +1,15 @@ # Changelog +## 2.7.1 + +Released 2018-09-29 + +* Added new ASCII convenience rule [`forty_two`](Rule-Reference.md#forty_two-c-). +* Added experimental `if_then` rule. +* Simplified how parse tree nodes can be selected. +* Reduced the number of intermediate parse tree nodes. +* Allowed an action class template to be used with the parse tree. + ## 2.7.0 Released 2018-07-31 diff -Nru tao-pegtl-2.7.0/doc/Installing-and-Using.md tao-pegtl-2.7.1/doc/Installing-and-Using.md --- tao-pegtl-2.7.0/doc/Installing-and-Using.md 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/doc/Installing-and-Using.md 2018-10-02 14:31:17.000000000 +0000 @@ -10,7 +10,6 @@ * [Embedding in Binaries](#embedding-in-binaries) * [Embedding in Libraries](#embedding-in-libraries) * [Embedding in Library Interfaces](#embedding-in-library-interfaces) -* [Limitations](#limitations) ## Requirements diff -Nru tao-pegtl-2.7.0/doc/README.md tao-pegtl-2.7.1/doc/README.md --- tao-pegtl-2.7.0/doc/README.md 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/doc/README.md 2018-10-02 14:31:17.000000000 +0000 @@ -121,6 +121,7 @@ * [`eolf`](Rule-Reference.md#eolf) [(ascii rules)](Rule-Reference.md#ascii-rules) * [`extender`](Rule-Reference.md#extender) [(icu rules)](Rule-Reference.md#icu-rules-for-binary-properties) * [`failure`](Rule-Reference.md#failure) [(atomic rules)](Rule-Reference.md#atomic-rules) +* [`forty_two< C... >`](Rule-Reference.md#forty_two-c-) [(ascii rules)](Rule-Reference.md#ascii-rules) * [`full_composition_exclusion`](Rule-Reference.md#full_composition_exclusion) [(icu rules)](Rule-Reference.md#icu-rules-for-binary-properties) * [`general_category< V >`](Rule-Reference.md#general_category-v-) [(icu rules)](Rule-Reference.md#icu-rules-for-enumerated-properties) * [`grapheme_base`](Rule-Reference.md#grapheme_base) [(icu rules)](Rule-Reference.md#icu-rules-for-binary-properties) diff -Nru tao-pegtl-2.7.0/doc/Rule-Reference.md tao-pegtl-2.7.1/doc/Rule-Reference.md --- tao-pegtl-2.7.0/doc/Rule-Reference.md 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/doc/Rule-Reference.md 2018-10-02 14:31:17.000000000 +0000 @@ -408,6 +408,10 @@ * Equivalent to `sor< eof, eol >`. +###### `forty_two< C... >` + +* Equivalent to `rep< 42, one< C... > >`. + ###### `identifier_first` * Matches and consumes a single ASCII character permissible as first character of a C identifier. @@ -494,7 +498,7 @@ ###### `space` * Matches and consumes a single space, line-feed, carriage-return, horizontal-tab, vertical-tab or form-feed. -* Equivalent to `one< ' ', '\n', '\r', 't', '\v', '\f' >`. +* Equivalent to `one< ' ', '\n', '\r', '\t', '\v', '\f' >`. ###### `string< C... >` @@ -573,7 +577,7 @@ * for UTF-16 the rules are surrogate-pair-aware and N is either 2 or 4, and * for UTF-32 everything is simple and N is always 4. -Following what appears to be "best" practice for UTF-16, it is *not* an error when a code unit in the range `0xd800` to `0xdfff` is encountered outside of a valid surrogate pair! +It is an error when a code unit in the range `0xd800` to `0xdfff` is encountered outside of a valid UTF-16 surrogate pair (this changed in version 2.6.0). ###### `any` @@ -1097,6 +1101,7 @@ * [`eolf`](#eolf) [(ascii rules)](#ascii-rules) * [`extender`](#extender) [(icu rules)](#icu-rules-for-binary-properties) * [`failure`](#failure) [(atomic rules)](#atomic-rules) +* [`forty_two< C... >`](#forty_two-c-) [(ascii rules)](#ascii-rules) * [`full_composition_exclusion`](#full_composition_exclusion) [(icu rules)](#icu-rules-for-binary-properties) * [`general_category< V >`](#general_category-v-) [(icu rules)](#icu-rules-for-enumerated-properties) * [`grapheme_base`](#grapheme_base) [(icu rules)](#icu-rules-for-binary-properties) diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/ascii.hpp tao-pegtl-2.7.1/include/tao/pegtl/ascii.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/ascii.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/ascii.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -23,6 +23,7 @@ struct blank : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {}; struct digit : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {}; struct eolf : internal::eolf {}; + template< char... Cs > struct forty_two : internal::rep< 42, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, Cs... > > {}; struct identifier_first : internal::identifier_first {}; struct identifier_other : internal::identifier_other {}; struct identifier : internal::identifier {}; diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/buffer_input.hpp tao-pegtl-2.7.1/include/tao/pegtl/buffer_input.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/buffer_input.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/buffer_input.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -176,6 +176,7 @@ iterator_t m_current; char* m_end; const Source m_source; + void* internal_state = nullptr; }; } // namespace TAO_PEGTL_NAMESPACE diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/contrib/changes.hpp tao-pegtl-2.7.1/include/tao/pegtl/contrib/changes.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/contrib/changes.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/contrib/changes.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -7,6 +7,8 @@ #include "../config.hpp" #include "../normal.hpp" +#include "../internal/conditional.hpp" + namespace tao { namespace TAO_PEGTL_NAMESPACE @@ -21,23 +23,6 @@ } }; - template< bool > - struct conditional; - - template<> - struct conditional< true > - { - template< typename R, typename > - using type = R; - }; - - template<> - struct conditional< false > - { - template< typename, typename R > - using type = R; - }; - template< apply_mode A, typename State > using state_disable_helper = typename conditional< A == apply_mode::ACTION >::template type< State, dummy_disabled_state >; diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/contrib/if_then.hpp tao-pegtl-2.7.1/include/tao/pegtl/contrib/if_then.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/contrib/if_then.hpp 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/contrib/if_then.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_CONTRIB_IF_THEN_HPP +#define TAO_PEGTL_CONTRIB_IF_THEN_HPP + +#include + +#include "../config.hpp" + +#include "../internal/if_then_else.hpp" +#include "../internal/seq.hpp" +#include "../internal/skip_control.hpp" +#include "../internal/trivial.hpp" + +namespace tao +{ + namespace TAO_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename Then > + struct if_pair + { + }; + + template< typename... Pairs > + struct if_then; + + template< typename Cond, typename Then, typename... Pairs > + struct if_then< if_pair< Cond, Then >, Pairs... > + : if_then_else< Cond, Then, if_then< Pairs... > > + { + template< typename ElseCond, typename... Thens > + using else_if_then = if_then< if_pair< Cond, Then >, Pairs..., if_pair< ElseCond, seq< Thens... > > >; + + template< typename... Thens > + using else_then = if_then_else< Cond, Then, if_then< Pairs..., if_pair< trivial< true >, seq< Thens... > > > >; + }; + + template<> + struct if_then<> + : trivial< false > + { + }; + + template< typename... Pairs > + struct skip_control< if_then< Pairs... > > : std::true_type + { + }; + + } // namespace internal + + template< typename Cond, typename... Thens > + using if_then = internal::if_then< internal::if_pair< Cond, internal::seq< Thens... > > >; + + } // namespace TAO_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/contrib/parse_tree.hpp tao-pegtl-2.7.1/include/tao/pegtl/contrib/parse_tree.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/contrib/parse_tree.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/contrib/parse_tree.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -16,6 +16,9 @@ #include "../nothing.hpp" #include "../parse.hpp" +#include "../analysis/counted.hpp" +#include "../analysis/generic.hpp" +#include "../internal/conditional.hpp" #include "../internal/demangle.hpp" #include "../internal/iterator.hpp" @@ -163,7 +166,7 @@ } }; - template< typename Node, typename S, typename = void > + template< typename Node, typename Selector, typename = void > struct transform { template< typename... States > @@ -172,54 +175,102 @@ } }; - template< typename Node, typename S > - struct transform< Node, S, decltype( S::transform( std::declval< std::unique_ptr< Node >& >() ), void() ) > + template< typename Node, typename Selector > + struct transform< Node, Selector, decltype( Selector::transform( std::declval< std::unique_ptr< Node >& >() ), void() ) > { template< typename... States > - static void call( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( S::transform( n ) ) ) + static void call( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) ) { - S::transform( n, st... ); + Selector::transform( n, st... ); } }; - template< template< typename > class S, template< typename > class C > - struct make_control + template< unsigned Level, typename Analyse, template< typename... > class Selector > + struct is_leaf + : std::false_type { - template< typename Rule, bool > - struct control; + }; - template< typename Rule > - using type = control< Rule, S< Rule >::value >; + template< analysis::rule_type Type, template< typename... > class Selector > + struct is_leaf< 0, analysis::generic< Type >, Selector > + : std::true_type + { + }; + + template< analysis::rule_type Type, unsigned Count, template< typename... > class Selector > + struct is_leaf< 0, analysis::counted< Type, Count >, Selector > + : std::true_type + { + }; + + template< analysis::rule_type Type, typename... Rules, template< typename... > class Selector > + struct is_leaf< 0, analysis::generic< Type, Rules... >, Selector > + : std::false_type + { + }; + + template< analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector > + struct is_leaf< 0, analysis::counted< Type, Count, Rules... >, Selector > + : std::false_type + { + }; + + template< bool... > + struct bool_sequence; + + template< bool... Bs > + using is_all = std::is_same< bool_sequence< Bs..., true >, bool_sequence< true, Bs... > >; + + template< unsigned Level, typename Rule, template< typename... > class Selector > + using is_unselected_leaf = std::integral_constant< bool, !Selector< Rule >::value && is_leaf< Level, typename Rule::analyze_t, Selector >::value >; + + template< unsigned Level, analysis::rule_type Type, typename... Rules, template< typename... > class Selector > + struct is_leaf< Level, analysis::generic< Type, Rules... >, Selector > + : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... > + { }; - template< typename Control, template< typename... > class Action, typename Input, typename... States > - struct return_type_apply0 + template< unsigned Level, analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector > + struct is_leaf< Level, analysis::counted< Type, Count, Rules... >, Selector > + : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... > { - using type = decltype( Control::template apply0< Action >( std::declval< const Input& >(), std::declval< States&& >()... ) ); }; - template< typename Control, template< typename... > class Action, typename Iterator, typename Input, typename... States > - struct return_type_apply + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + struct make_control + { + template< typename Rule, bool, bool > + struct control; + + template< typename Rule > + using type = control< Rule, Selector< Rule >::value, is_leaf< 8, typename Rule::analyze_t, Selector >::value >; + }; + + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + template< typename Rule > + struct make_control< Node, Selector, Control >::control< Rule, false, true > + : Control< Rule > { - using type = decltype( Control::template apply< Action >( std::declval< const Iterator& >(), std::declval< const Input& >(), std::declval< States&& >()... ) ); }; - template< template< typename > class S, template< typename > class C > + template< typename Node, template< typename... > class Selector, template< typename... > class Control > template< typename Rule > - struct make_control< S, C >::control< Rule, false > - : C< Rule > + struct make_control< Node, Selector, Control >::control< Rule, false, false > + : Control< Rule > { - template< typename Input, typename Node, typename... States > - static void start( const Input& in, state< Node >& state, States&&... st ) + template< typename Input, typename... States > + static void start( const Input& in, States&&... st ) { - C< Rule >::start( in, st... ); + Control< Rule >::start( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); state.emplace_back(); } - template< typename Input, typename Node, typename... States > - static void success( const Input& in, state< Node >& state, States&&... st ) + template< typename Input, typename... States > + static void success( const Input& in, States&&... st ) { - C< Rule >::success( in, st... ); + Control< Rule >::success( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); auto n = std::move( state.back() ); state.pop_back(); for( auto& c : n->children ) { @@ -227,83 +278,56 @@ } } - template< typename Input, typename Node, typename... States > - static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( C< Rule >::failure( in, st... ) ) ) + template< typename Input, typename... States > + static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) { - C< Rule >::failure( in, st... ); + Control< Rule >::failure( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); state.pop_back(); } - - template< typename Input, typename Node, typename... States > - static void raise( const Input& in, state< Node >& /*unused*/, States&&... st ) - { - C< Rule >::raise( in, st... ); - } - - template< template< typename... > class Action, typename Input, typename Node, typename... States > - static typename return_type_apply0< C< Rule >, Action, Input, States... >::type apply0( const Input& in, state< Node >& /*unused*/, States&&... st ) - { - return C< Rule >::template apply0< Action >( in, st... ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename Node, typename... States > - static typename return_type_apply< C< Rule >, Action, Iterator, Input, States... >::type apply( const Iterator& begin, const Input& in, state< Node >& /*unused*/, States&&... st ) - { - return C< Rule >::template apply< Action >( begin, in, st... ); - } }; - template< template< typename > class S, template< typename > class C > - template< typename Rule > - struct make_control< S, C >::control< Rule, true > - : C< Rule > + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + template< typename Rule, bool B > + struct make_control< Node, Selector, Control >::control< Rule, true, B > + : Control< Rule > { - template< typename Input, typename Node, typename... States > - static void start( const Input& in, state< Node >& state, States&&... st ) + template< typename Input, typename... States > + static void start( const Input& in, States&&... st ) { - C< Rule >::start( in, st... ); + Control< Rule >::start( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); state.emplace_back(); state.back()->template start< Rule >( in, st... ); } - template< typename Input, typename Node, typename... States > - static void success( const Input& in, state< Node >& state, States&&... st ) + template< typename Input, typename... States > + static void success( const Input& in, States&&... st ) { - C< Rule >::success( in, st... ); + Control< Rule >::success( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); auto n = std::move( state.back() ); state.pop_back(); n->template success< Rule >( in, st... ); - transform< Node, S< Rule > >::call( n, st... ); + transform< Node, Selector< Rule > >::call( n, st... ); if( n ) { state.back()->emplace_back( std::move( n ), st... ); } } - template< typename Input, typename Node, typename... States > - static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( C< Rule >::failure( in, st... ) ) && noexcept( std::declval< node& >().template failure< Rule >( in, st... ) ) ) + template< typename Input, typename... States > + static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< node& >().template failure< Rule >( in, st... ) ) ) { - C< Rule >::failure( in, st... ); + Control< Rule >::failure( in, st... ); + auto& state = *static_cast< internal::state< Node >* >( in.internal_state ); state.back()->template failure< Rule >( in, st... ); state.pop_back(); } + }; - template< typename Input, typename Node, typename... States > - static void raise( const Input& in, state< Node >& /*unused*/, States&&... st ) - { - C< Rule >::raise( in, st... ); - } - - template< template< typename... > class Action, typename Input, typename Node, typename... States > - static typename return_type_apply0< C< Rule >, Action, Input, States... >::type apply0( const Input& in, state< Node >& /*unused*/, States&&... st ) - { - return C< Rule >::template apply0< Action >( in, st... ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename Node, typename... States > - static typename return_type_apply< C< Rule >, Action, Iterator, Input, States... >::type apply( const Iterator& begin, const Input& in, state< Node >& /*unused*/, States&&... st ) - { - return C< Rule >::template apply< Action >( begin, in, st... ); - } + template< typename > + struct element + { }; template< typename > @@ -313,6 +337,14 @@ } // namespace internal + struct store_content : std::true_type + { + template< typename Node, typename... States > + static void transform( std::unique_ptr< Node >& /*unused*/, States&&... /*unused*/ ) noexcept + { + } + }; + // some nodes don't need to store their content struct remove_content : std::true_type { @@ -323,45 +355,101 @@ } }; - // if a node has only one child, replace the node with its child - struct fold_one : std::true_type + // if a node has only one child, replace the node with its child, otherwise apply B + template< typename Base > + struct fold_one_or : Base { template< typename Node, typename... States > - static void transform( std::unique_ptr< Node >& n, States&&... /*unused*/ ) noexcept( noexcept( n->children.size(), n->children.front() ) ) + static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), Base::transform( n, st... ) ) ) { if( n->children.size() == 1 ) { n = std::move( n->children.front() ); } + else { + Base::transform( n, st... ); + } } }; - // if a node has no children, discard the node - struct discard_empty : std::true_type + // if a node has no children, discard the node, otherwise apply B + template< typename Base > + struct discard_empty_or : Base { template< typename Node, typename... States > - static void transform( std::unique_ptr< Node >& n, States&&... /*unused*/ ) noexcept( noexcept( n->children.empty() ) ) + static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), Base::transform( n, st... ) ) ) { if( n->children.empty() ) { n.reset(); } + else { + Base::transform( n, st... ); + } } }; - template< typename Rule, typename Node, template< typename > class S = internal::store_all, template< typename > class C = normal, typename Input, typename... States > + using fold_one = fold_one_or< remove_content >; + using discard_empty = discard_empty_or< remove_content >; + + template< typename Rule, typename... Collections > + struct selector : std::false_type + { + }; + + // TODO: Implement in a non-recursive way + // TODO: Check for multiple matches (currently: first match wins) + template< typename Rule, typename Collection, typename... Collections > + struct selector< Rule, Collection, Collections... > + : TAO_PEGTL_NAMESPACE::internal::conditional< Collection::template contains< Rule >::value >::template type< typename Collection::type, selector< Rule, Collections... > > + { + }; + + template< typename Base > + struct apply + { + template< typename... Rules > + struct to + : internal::element< Rules >... + { + using type = Base; + + template< typename Rule > + using contains = std::is_base_of< internal::element< Rule >, to >; + }; + }; + + using apply_store_content = apply< store_content >; + using apply_remove_content = apply< remove_content >; + using apply_fold_one = apply< fold_one >; + using apply_discard_empty = apply< discard_empty >; + + template< typename Rule, + typename Node, + template< typename... > class Selector = internal::store_all, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename Input, + typename... States > std::unique_ptr< Node > parse( Input&& in, States&&... st ) { internal::state< Node > state; - if( !TAO_PEGTL_NAMESPACE::parse< Rule, nothing, internal::make_control< S, C >::template type >( in, state, st... ) ) { + assert( in.internal_state == nullptr ); + in.internal_state = &state; + if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st... ) ) { return nullptr; } assert( state.stack.size() == 1 ); return std::move( state.back() ); } - template< typename Rule, template< typename > class S = internal::store_all, template< typename > class C = normal, typename Input, typename... States > + template< typename Rule, + template< typename... > class Selector = internal::store_all, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename Input, + typename... States > std::unique_ptr< node > parse( Input&& in, States&&... st ) { - return parse< Rule, node, S, C >( in, st... ); + return parse< Rule, node, Selector, Action, Control >( in, st... ); } } // namespace parse_tree diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/contrib/raw_string.hpp tao-pegtl-2.7.1/include/tao/pegtl/contrib/raw_string.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/contrib/raw_string.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/contrib/raw_string.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -69,7 +69,7 @@ template< char Marker, char Close > struct at_raw_string_close { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; + using analyze_t = analysis::generic< analysis::rule_type::OPT >; template< apply_mode A, rewind_mode, @@ -189,8 +189,6 @@ template< char Open, char Marker, char Close, typename... Contents > struct raw_string { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - // This is used for binding the apply()-method and for error-reporting // when a raw string is not closed properly or has invalid content. struct content @@ -198,6 +196,8 @@ { }; + using analyze_t = typename internal::seq< internal::bytes< 1 >, content, internal::bytes< 1 > >::analyze_t; + template< apply_mode A, rewind_mode M, template< typename... > class Action, diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/contrib/unescape.hpp tao-pegtl-2.7.1/include/tao/pegtl/contrib/unescape.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/contrib/unescape.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/contrib/unescape.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -122,24 +122,26 @@ static void apply( const Input& in, State& st ) { assert( in.size() == 1 ); - st.unescaped += apply_one( *in.begin(), static_cast< const T* >( nullptr ) ); + st.unescaped += apply_one( in, static_cast< const T* >( nullptr ) ); } - template< char... Qs > - static char apply_one( const char c, const one< Qs... >* /*unused*/ ) + template< typename Input, char... Qs > + static char apply_one( const Input& in, const one< Qs... >* /*unused*/ ) { static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" ); - return apply_two( c, { Qs... }, { Rs... } ); + return apply_two( in, { Qs... }, { Rs... } ); } - static char apply_two( const char c, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) + template< typename Input > + static char apply_two( const Input& in, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) { + const char c = *in.begin(); for( std::size_t i = 0; i < q.size(); ++i ) { if( *( q.begin() + i ) == c ) { return *( r.begin() + i ); } } - throw std::runtime_error( "invalid character in unescape" ); // NOLINT, LCOV_EXCL_LINE + throw parse_error( "invalid character in unescape", in ); // NOLINT, LCOV_EXCL_LINE } }; diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/internal/conditional.hpp tao-pegtl-2.7.1/include/tao/pegtl/internal/conditional.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/internal/conditional.hpp 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/internal/conditional.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -0,0 +1,38 @@ +// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_INTERNAL_CONDITIONAL_HPP +#define TAO_PEGTL_INTERNAL_CONDITIONAL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAO_PEGTL_NAMESPACE + { + namespace internal + { + template< bool > + struct conditional; + + template<> + struct conditional< true > + { + template< typename T, typename > + using type = T; + }; + + template<> + struct conditional< false > + { + template< typename, typename T > + using type = T; + }; + + } // namespace internal + + } // namespace TAO_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/internal/file_mapper_win32.hpp tao-pegtl-2.7.1/include/tao/pegtl/internal/file_mapper_win32.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/internal/file_mapper_win32.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/internal/file_mapper_win32.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -14,7 +14,7 @@ #define TAO_PEGTL_WIN32_MEAN_AND_LEAN_WAS_DEFINED #endif -#include +#include #if defined( TAO_PEGTL_NOMINMAX_WAS_DEFINED ) #undef NOMINMAX diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/memory_input.hpp tao-pegtl-2.7.1/include/tao/pegtl/memory_input.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/memory_input.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/memory_input.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -350,6 +350,8 @@ { return std::string( begin_of_line( p ), end_of_line( p ) ); } + + void* internal_state = nullptr; }; #ifdef __cpp_deduction_guides diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/parse.hpp tao-pegtl-2.7.1/include/tao/pegtl/parse.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/parse.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/parse.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -4,6 +4,8 @@ #ifndef TAO_PEGTL_PARSE_HPP #define TAO_PEGTL_PARSE_HPP +#include + #include "apply_mode.hpp" #include "config.hpp" #include "normal.hpp" @@ -11,10 +13,37 @@ #include "parse_error.hpp" #include "rewind_mode.hpp" +#include "internal/action_input.hpp" + namespace tao { namespace TAO_PEGTL_NAMESPACE { + namespace internal + { + template< typename From > + struct copy_internals + { + template< typename To > + static void apply( const From& from, To& to ) noexcept + { + assert( to.internal_state == nullptr ); + to.internal_state = from.internal_state; + } + }; + + template< typename Input > + struct copy_internals< action_input< Input > > + { + template< typename To > + static void apply( const action_input< Input >& from, To& to ) noexcept + { + assert( to.internal_state == nullptr ); + to.internal_state = from.input().internal_state; + } + }; + } // namespace internal + template< typename Rule, template< typename... > class Action = nothing, template< typename... > class Control = normal, @@ -38,6 +67,7 @@ bool parse_nested( const Outer& oi, Input&& in, States&&... st ) { try { + internal::copy_internals< Outer >::apply( oi, in ); return parse< Rule, Action, Control, A, M >( in, st... ); } catch( parse_error& e ) { diff -Nru tao-pegtl-2.7.0/include/tao/pegtl/version.hpp tao-pegtl-2.7.1/include/tao/pegtl/version.hpp --- tao-pegtl-2.7.0/include/tao/pegtl/version.hpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/include/tao/pegtl/version.hpp 2018-10-02 14:31:17.000000000 +0000 @@ -4,11 +4,11 @@ #ifndef TAO_PEGTL_VERSION_HPP #define TAO_PEGTL_VERSION_HPP -#define TAO_PEGTL_VERSION "2.7.0" +#define TAO_PEGTL_VERSION "2.7.1" #define TAO_PEGTL_VERSION_MAJOR 2 #define TAO_PEGTL_VERSION_MINOR 7 -#define TAO_PEGTL_VERSION_PATCH 0 +#define TAO_PEGTL_VERSION_PATCH 1 // Compatibility, remove with 3.0 #define TAOCPP_PEGTL_VERSION TAO_PEGTL_VERSION diff -Nru tao-pegtl-2.7.0/README.md tao-pegtl-2.7.1/README.md --- tao-pegtl-2.7.0/README.md 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/README.md 2018-10-02 14:31:17.000000000 +0000 @@ -68,7 +68,7 @@ * Mac OS X 10.10, Xcode 6.4 * Mac OS X 10.11, Xcode 7.3 * macOS 10.12, Xcode 8.3 - * macOS 10.13, Xcode 9.3 + * macOS 10.13, Xcode 9.4 * Linux (using libstdc++) diff -Nru tao-pegtl-2.7.0/src/example/pegtl/abnf2pegtl.cpp tao-pegtl-2.7.1/src/example/pegtl/abnf2pegtl.cpp --- tao-pegtl-2.7.0/src/example/pegtl/abnf2pegtl.cpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/src/example/pegtl/abnf2pegtl.cpp 2018-10-02 14:31:17.000000000 +0000 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -33,35 +34,98 @@ { namespace abnf { + using node_ptr = std::unique_ptr< parse_tree::node >; + namespace { std::string prefix = "tao::pegtl::"; // NOLINT - // clang-format off std::set< std::string > keywords = { // NOLINT - "alignas", "alignof", "and", "and_eq", - "asm", "auto", "bitand", "bitor", - "bool", "break", "case", "catch", - "char", "char16_t", "char32_t", "class", - "compl", "const", "constexpr", "const_cast", - "continue", "decltype", "default", "delete", - "do", "double", "dynamic_cast", "else", - "enum", "explicit", "export", "extern", - "false", "float", "for", "friend", - "goto", "if", "inline", "int", - "long", "mutable", "namespace", "new", - "noexcept", "not", "not_eq", "nullptr", - "operator", "or", "or_eq", "private", - "protected", "public", "register", "reinterpret_cast", - "return", "short", "signed", "sizeof", - "static", "static_assert", "static_cast", "struct", - "switch", "template", "this", "thread_local", - "throw", "true", "try", "typedef", - "typeid", "typename", "union", "unsigned", - "using", "virtual", "void", "volatile", - "wchar_t", "while", "xor", "xor_eq" + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "const", + "constexpr", + "const_cast", + "continue", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq" }; - // clang-format on using rules_t = std::vector< std::string >; rules_t rules_defined; // NOLINT @@ -238,22 +302,45 @@ template<> const std::string error_control< defined_as >::error_message = "expected '=' or '=/'"; // NOLINT template<> const std::string error_control< c_nl >::error_message = "unterminated rule"; // NOLINT template<> const std::string error_control< rule >::error_message = "expected rule"; // NOLINT + // clang-format on } // namespace grammar - struct node - : tao::TAO_PEGTL_NAMESPACE::parse_tree::basic_node< node > + template< typename Rule > + struct selector + : parse_tree::selector< + Rule, + parse_tree::apply_store_content::to< + grammar::rulename, + grammar::prose_val, + grammar::hex_val::value, + grammar::dec_val::value, + grammar::bin_val::value, + grammar::hex_val::range, + grammar::dec_val::range, + grammar::bin_val::range, + grammar::hex_val::type, + grammar::dec_val::type, + grammar::bin_val::type, + grammar::repeat, + grammar::defined_as_op >, + parse_tree::apply_remove_content::to< + grammar::option, + grammar::and_predicate, + grammar::not_predicate, + grammar::rule >, + parse_tree::apply_fold_one::to< + grammar::alternation, + grammar::group, + grammar::repetition, + grammar::concatenation > > { - template< typename... States > - void emplace_back( std::unique_ptr< node > child, States&&... st ); }; - template< typename Rule > struct selector : std::false_type {}; - template<> struct selector< grammar::rulename > : std::true_type {}; - - template<> struct selector< grammar::quoted_string > : std::true_type + template<> + struct selector< grammar::quoted_string > : std::true_type { - static void transform( std::unique_ptr< node >& n ) + static void transform( node_ptr& n ) { shift( n->m_begin, 1 ); shift( n->m_end, -1 ); @@ -274,9 +361,10 @@ } }; - template<> struct selector< grammar::case_sensitive_string > : std::true_type + template<> + struct selector< grammar::case_sensitive_string > : std::true_type { - static void transform( std::unique_ptr< node >& n ) + static void transform( node_ptr& n ) { n = std::move( n->children.back() ); if( n->content().size() == 1 ) { @@ -288,34 +376,20 @@ } }; - template<> struct selector< grammar::prose_val > : std::true_type {}; - template<> struct selector< grammar::hex_val::value > : std::true_type {}; - template<> struct selector< grammar::dec_val::value > : std::true_type {}; - template<> struct selector< grammar::bin_val::value > : std::true_type {}; - template<> struct selector< grammar::hex_val::range > : std::true_type {}; - template<> struct selector< grammar::dec_val::range > : std::true_type {}; - template<> struct selector< grammar::bin_val::range > : std::true_type {}; - template<> struct selector< grammar::hex_val::type > : std::true_type {}; - template<> struct selector< grammar::dec_val::type > : std::true_type {}; - template<> struct selector< grammar::bin_val::type > : std::true_type {}; - template<> struct selector< grammar::alternation > : parse_tree::fold_one {}; - template<> struct selector< grammar::option > : std::true_type {}; - template<> struct selector< grammar::group > : parse_tree::fold_one {}; - template<> struct selector< grammar::repeat > : std::true_type {}; - template<> struct selector< grammar::repetition > : parse_tree::fold_one {}; - template<> struct selector< grammar::and_predicate > : std::true_type {}; - template<> struct selector< grammar::not_predicate > : std::true_type {}; - template<> struct selector< grammar::concatenation > : parse_tree::fold_one {}; - template<> struct selector< grammar::defined_as_op > : std::true_type {}; - template<> struct selector< grammar::rule > : std::true_type {}; - // clang-format on + std::string to_string( const node_ptr& n ); + std::string to_string( const std::vector< node_ptr >& v ); - std::string to_string( const std::unique_ptr< node >& n ); - std::string to_string( const std::vector< std::unique_ptr< node > >& v ); + std::string to_string_unwrap_seq( const node_ptr& n ) + { + if( n->is< grammar::group >() || n->is< grammar::concatenation >() ) { + return to_string( n->children ); + } + return to_string( n ); + } namespace { - std::string get_rulename( const std::unique_ptr< node >& n ) + std::string get_rulename( const node_ptr& n ) { assert( n->is< grammar::rulename >() ); std::string v = n->content(); @@ -323,7 +397,7 @@ return v; } - std::string get_rulename( const std::unique_ptr< node >& n, const bool print_forward_declarations ) + std::string get_rulename( const node_ptr& n, const bool print_forward_declarations ) { std::string v = get_rulename( n ); const auto it = find_rule( rules, v ); @@ -331,7 +405,7 @@ return *it; } if( keywords.count( v ) != 0 || v.find( "__" ) != std::string::npos ) { - throw std::runtime_error( to_string( n->begin() ) + ": '" + v + "' is a reserved rulename" ); // NOLINT + throw parse_error( '\'' + n->content() + "' is a reserved rulename", n->begin() ); // NOLINT } if( print_forward_declarations && find_rule( rules_defined, v ) != rules_defined.rend() ) { std::cout << "struct " << v << ";\n"; @@ -341,7 +415,7 @@ } template< typename T > - std::string gen_val( const std::unique_ptr< node >& n ) + std::string gen_val( const node_ptr& n ) { if( n->children.size() == 2 ) { if( n->children.back()->is< T >() ) { @@ -354,87 +428,78 @@ return prefix + "string< " + to_string( n->children ) + " >"; } + struct ccmp + { + bool operator()( const std::string& lhs, const std::string& rhs ) const noexcept + { + return TAO_PEGTL_STRCASECMP( lhs.c_str(), rhs.c_str() ) < 0; + } + }; + + std::map< std::string, parse_tree::node*, ccmp > previous_rules; // NOLINT + } // namespace - template< typename... States > - void node::emplace_back( std::unique_ptr< node > child, States&&... st ) + template<> + struct selector< grammar::rule > : std::true_type { - // inserting a rule is handled here since we need access to all previously inserted rules - if( child->is< grammar::rule >() ) { - const auto rname = get_rulename( child->children.front() ); - assert( child->children.at( 1 )->is< grammar::defined_as_op >() ); - const auto op = child->children.at( 1 )->content(); + static void transform( node_ptr& n ) + { + const auto rname = get_rulename( n->children.front() ); + assert( n->children.at( 1 )->is< grammar::defined_as_op >() ); + const auto op = n->children.at( 1 )->content(); // when we insert a normal rule, we need to check for duplicates if( op == "=" ) { - for( const auto& n : children ) { - if( TAO_PEGTL_STRCASECMP( rname.c_str(), abnf::get_rulename( n->children.front() ).c_str() ) == 0 ) { - throw std::runtime_error( to_string( child->begin() ) + ": rule '" + rname + "' is already defined" ); // NOLINT - } + if( !previous_rules.insert( { rname, n.get() } ).second ) { + throw parse_error( "rule '" + rname + "' is already defined", n->begin() ); // NOLINT } } // if it is an "incremental alternation", we need to consolidate the assigned alternations else if( op == "=/" ) { - std::size_t i = 0; - while( i < children.size() ) { - if( TAO_PEGTL_STRCASECMP( rname.c_str(), abnf::get_rulename( children.at( i )->children.front() ).c_str() ) == 0 ) { - auto& previous = children.at( i )->children.back(); - - // if the previous rule does not assign an alternation, create an intermediate alternation and move its assignee into it. - if( !previous->is< abnf::grammar::alternation >() ) { - std::unique_ptr< node > s( new node ); - s->id = &typeid( abnf::grammar::alternation ); - s->source = previous->source; - s->m_begin = previous->m_begin; - s->m_end = previous->m_end; - s->children.emplace_back( std::move( previous ) ); - previous = std::move( s ); - } - - // append all new options to the previous rule's assignee (which now always an alternation) - previous->m_end = child->children.back()->m_end; - - // if the new rule itself contains an alternation, append the individual entries... - if( child->children.back()->is< abnf::grammar::alternation >() ) { - for( auto& n : child->children.back()->children ) { - previous->children.emplace_back( std::move( n ) ); - } - } - // ...otherwise add the node itself as another option. - else { - previous->children.emplace_back( std::move( child->children.back() ) ); - } + const auto p = previous_rules.find( rname ); + if( p == previous_rules.end() ) { + throw parse_error( "incremental alternation '" + rname + "' without previous rule definition", n->begin() ); // NOLINT + } + auto& previous = p->second->children.back(); - // finally, move the previous rule to the current position... - child = std::move( children.at( i ) ); + // if the previous rule does not assign an alternation, create an intermediate alternation and move its assignee into it. + if( !previous->is< abnf::grammar::alternation >() ) { + node_ptr s( new parse_tree::node ); + s->id = &typeid( abnf::grammar::alternation ); + s->source = previous->source; + s->m_begin = previous->m_begin; + s->m_end = previous->m_end; + s->children.emplace_back( std::move( previous ) ); + previous = std::move( s ); + } - // ...and remove the previous rule from the list. - children.erase( children.begin() + i ); + // append all new options to the previous rule's assignee (which always is an alternation now) + previous->m_end = n->children.back()->m_end; - // all OK now - break; + // if the new rule itself contains an alternation, append the individual entries... + if( n->children.back()->is< abnf::grammar::alternation >() ) { + for( auto& e : n->children.back()->children ) { + previous->children.emplace_back( std::move( e ) ); } - ++i; } - if( i == children.size() ) { - throw std::runtime_error( to_string( child->begin() ) + ": incremental alternation '" + rname + "' without previous rule definition" ); // NOLINT + // ...otherwise add the node itself as another option. + else { + previous->children.emplace_back( std::move( n->children.back() ) ); } + n.reset(); } else { - throw std::runtime_error( to_string( child->begin() ) + ": invalid operator '" + op + "', this should not happen!" ); // NOLINT + throw parse_error( "invalid operator '" + op + "', this should not happen!", n->begin() ); // NOLINT } } - - // perform the normal emplace_back operation by forwarding to the original method - tao::TAO_PEGTL_NAMESPACE::parse_tree::basic_node< node >::emplace_back( std::move( child ), st... ); - } + }; struct stringifier { - using function_t = std::string ( * )( const std::unique_ptr< node >& n ); + using function_t = std::string ( * )( const node_ptr& n ); function_t default_ = nullptr; - using map_t = std::map< const std::type_info*, function_t >; - map_t map_; + std::map< const std::type_info*, function_t > map_; template< typename T > void add( const function_t& f ) @@ -442,7 +507,7 @@ map_.insert( { &typeid( T ), f } ); } - std::string operator()( const std::unique_ptr< node >& n ) const + std::string operator()( const node_ptr& n ) const { const auto it = map_.find( n->id ); if( it != map_.end() ) { @@ -455,17 +520,17 @@ stringifier make_stringifier() { stringifier nrv; - nrv.default_ = []( const std::unique_ptr< node >& n ) -> std::string { - throw std::runtime_error( to_string( n->begin() ) + ": missing to_string() for " + n->name() ); // NOLINT + nrv.default_ = []( const node_ptr& n ) -> std::string { + throw parse_error( "missing to_string() for " + n->name(), n->begin() ); // NOLINT }; - nrv.add< grammar::rulename >( []( const std::unique_ptr< node >& n ) { return get_rulename( n, true ); } ); + nrv.add< grammar::rulename >( []( const node_ptr& n ) { return get_rulename( n, true ); } ); - nrv.add< grammar::rule >( []( const std::unique_ptr< node >& n ) { + nrv.add< grammar::rule >( []( const node_ptr& n ) { return "struct " + get_rulename( n->children.front(), false ) + " : " + to_string( n->children.back() ) + " {};"; } ); - nrv.add< string_tag >( []( const std::unique_ptr< node >& n ) { + nrv.add< string_tag >( []( const node_ptr& n ) { const std::string content = n->content(); std::string s; for( const auto c : content ) { @@ -474,7 +539,7 @@ return prefix + "string< " + s + " >"; } ); - nrv.add< istring_tag >( []( const std::unique_ptr< node >& n ) { + nrv.add< istring_tag >( []( const node_ptr& n ) { const std::string content = n->content(); std::string s; for( const auto c : content ) { @@ -483,7 +548,7 @@ return prefix + "istring< " + s + " >"; } ); - nrv.add< one_tag >( []( const std::unique_ptr< node >& n ) { + nrv.add< one_tag >( []( const node_ptr& n ) { const std::string content = n->content(); std::string s; for( const auto c : content ) { @@ -492,9 +557,9 @@ return prefix + "one< " + s + " >"; } ); - nrv.add< grammar::hex_val::value >( []( const std::unique_ptr< node >& n ) { return "0x" + n->content(); } ); - nrv.add< grammar::dec_val::value >( []( const std::unique_ptr< node >& n ) { return n->content(); } ); - nrv.add< grammar::bin_val::value >( []( const std::unique_ptr< node >& n ) { + nrv.add< grammar::hex_val::value >( []( const node_ptr& n ) { return "0x" + n->content(); } ); + nrv.add< grammar::dec_val::value >( []( const node_ptr& n ) { return n->content(); } ); + nrv.add< grammar::bin_val::value >( []( const node_ptr& n ) { unsigned long long v = 0; const char* p = n->m_begin.data; // TODO: Detect overflow @@ -507,47 +572,47 @@ return o.str(); } ); - nrv.add< grammar::hex_val::type >( []( const std::unique_ptr< node >& n ) { return gen_val< grammar::hex_val::range >( n ); } ); - nrv.add< grammar::dec_val::type >( []( const std::unique_ptr< node >& n ) { return gen_val< grammar::dec_val::range >( n ); } ); - nrv.add< grammar::bin_val::type >( []( const std::unique_ptr< node >& n ) { return gen_val< grammar::bin_val::range >( n ); } ); + nrv.add< grammar::hex_val::type >( []( const node_ptr& n ) { return gen_val< grammar::hex_val::range >( n ); } ); + nrv.add< grammar::dec_val::type >( []( const node_ptr& n ) { return gen_val< grammar::dec_val::range >( n ); } ); + nrv.add< grammar::bin_val::type >( []( const node_ptr& n ) { return gen_val< grammar::bin_val::range >( n ); } ); - nrv.add< grammar::alternation >( []( const std::unique_ptr< node >& n ) { return prefix + "sor< " + to_string( n->children ) + " >"; } ); - nrv.add< grammar::option >( []( const std::unique_ptr< node >& n ) { return prefix + "opt< " + to_string( n->children ) + " >"; } ); - nrv.add< grammar::group >( []( const std::unique_ptr< node >& n ) { return prefix + "seq< " + to_string( n->children ) + " >"; } ); + nrv.add< grammar::alternation >( []( const node_ptr& n ) { return prefix + "sor< " + to_string( n->children ) + " >"; } ); + nrv.add< grammar::option >( []( const node_ptr& n ) { return prefix + "opt< " + to_string( n->children ) + " >"; } ); + nrv.add< grammar::group >( []( const node_ptr& n ) { return prefix + "seq< " + to_string( n->children ) + " >"; } ); - nrv.add< grammar::prose_val >( []( const std::unique_ptr< node >& n ) { return "/* " + n->content() + " */"; } ); + nrv.add< grammar::prose_val >( []( const node_ptr& n ) { return "/* " + n->content() + " */"; } ); - nrv.add< grammar::and_predicate >( []( const std::unique_ptr< node >& n ) { + nrv.add< grammar::and_predicate >( []( const node_ptr& n ) { assert( n->children.size() == 1 ); - return prefix + "at< " + to_string( n->children.front() ) + " >"; + return prefix + "at< " + to_string_unwrap_seq( n->children.front() ) + " >"; } ); - nrv.add< grammar::not_predicate >( []( const std::unique_ptr< node >& n ) { + nrv.add< grammar::not_predicate >( []( const node_ptr& n ) { assert( n->children.size() == 1 ); - return prefix + "not_at< " + to_string( n->children.front() ) + " >"; + return prefix + "not_at< " + to_string_unwrap_seq( n->children.front() ) + " >"; } ); - nrv.add< grammar::concatenation >( []( const std::unique_ptr< node >& n ) { + nrv.add< grammar::concatenation >( []( const node_ptr& n ) { assert( !n->children.empty() ); return prefix + "seq< " + to_string( n->children ) + " >"; } ); - nrv.add< grammar::repetition >( []( const std::unique_ptr< node >& n ) -> std::string { + nrv.add< grammar::repetition >( []( const node_ptr& n ) -> std::string { assert( n->children.size() == 2 ); - const auto content = to_string( n->children.back() ); + const auto content = to_string_unwrap_seq( n->children.back() ); const auto rep = n->children.front()->content(); const auto star = rep.find( '*' ); if( star == std::string::npos ) { const auto v = remove_leading_zeroes( rep ); if( v.empty() ) { - throw std::runtime_error( to_string( n->begin() ) + ": repetition of zero not allowed" ); // NOLINT + throw parse_error( "repetition of zero not allowed", n->begin() ); // NOLINT } return prefix + "rep< " + v + ", " + content + " >"; } const auto min = remove_leading_zeroes( rep.substr( 0, star ) ); const auto max = remove_leading_zeroes( rep.substr( star + 1 ) ); if( ( star != rep.size() - 1 ) && max.empty() ) { - throw std::runtime_error( to_string( n->begin() ) + ": repetition maximum of zero not allowed" ); // NOLINT + throw parse_error( "repetition maximum of zero not allowed", n->begin() ); // NOLINT } if( min.empty() && max.empty() ) { return prefix + "star< " + content + " >"; @@ -575,7 +640,11 @@ s >> max_val; } if( min_val > max_val ) { - throw std::runtime_error( to_string( n->begin() ) + ": repetition minimum which is greater than the repetition maximum not allowed" ); // NOLINT + throw parse_error( "repetition minimum which is greater than the repetition maximum not allowed", n->begin() ); // NOLINT + } + if( ( min_val == 1 ) && ( max_val == 1 ) ) { + // note: content can not be used here! + return to_string( n->children.back() ); } const auto min_element = ( min_val == 1 ) ? content : ( prefix + "rep< " + min + ", " + content + " >" ); if( min_val == max_val ) { @@ -590,13 +659,13 @@ return nrv; } - std::string to_string( const std::unique_ptr< node >& n ) + std::string to_string( const node_ptr& n ) { static stringifier s = make_stringifier(); return s( n ); } - std::string to_string( const std::vector< std::unique_ptr< node > >& v ) + std::string to_string( const std::vector< node_ptr >& v ) { std::string result; for( const auto& c : v ) { @@ -626,7 +695,7 @@ file_input<> in( argv[ 1 ] ); try { - const auto root = parse_tree::parse< abnf::grammar::rulelist, abnf::node, abnf::selector, abnf::grammar::error_control >( in ); + const auto root = parse_tree::parse< abnf::grammar::rulelist, abnf::selector, nothing, abnf::grammar::error_control >( in ); for( const auto& rule : root->children ) { abnf::rules_defined.push_back( abnf::get_rulename( rule->children.front() ) ); diff -Nru tao-pegtl-2.7.0/src/example/pegtl/CMakeLists.txt tao-pegtl-2.7.1/src/example/pegtl/CMakeLists.txt --- tao-pegtl-2.7.0/src/example/pegtl/CMakeLists.txt 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/src/example/pegtl/CMakeLists.txt 2018-10-02 14:31:17.000000000 +0000 @@ -38,6 +38,7 @@ endif () get_filename_component (exename ${examplesourcefile} NAME_WE) + set (exename "pegtl-example-${exename}") add_executable (${exename} ${examplesourcefile}) target_link_libraries (${exename} PRIVATE taocpp::pegtl) set_target_properties (${exename} PROPERTIES diff -Nru tao-pegtl-2.7.0/src/example/pegtl/parse_tree.cpp tao-pegtl-2.7.1/src/example/pegtl/parse_tree.cpp --- tao-pegtl-2.7.0/src/example/pegtl/parse_tree.cpp 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/src/example/pegtl/parse_tree.cpp 2018-10-02 14:31:17.000000000 +0000 @@ -33,24 +33,6 @@ struct expression : list_must< product, sor< plus, minus > > {}; struct grammar : seq< expression, eof > {}; - // clang-format on - - // select which rules in the grammar will produce parse tree nodes: - - // clang-format off - - // by default, nodes are not generated/stored - template< typename > struct store : std::false_type {}; - - // select which rules in the grammar will produce parse tree nodes: - template<> struct store< integer > : std::true_type {}; - template<> struct store< variable > : std::true_type {}; - - template<> struct store< plus > : parse_tree::remove_content {}; - template<> struct store< minus > : parse_tree::remove_content {}; - template<> struct store< multiply > : parse_tree::remove_content {}; - template<> struct store< divide > : parse_tree::remove_content {}; - // clang-format on // after a node is stored successfully, you can add an optional transformer like this: struct rearrange : std::true_type @@ -76,6 +58,7 @@ n = std::move( n->children.back() ); } else { + n->remove_content(); auto& c = n->children; auto r = std::move( c.back() ); c.pop_back(); @@ -89,10 +72,22 @@ } }; - // clang-format off - template<> struct store< product > : rearrange {}; - template<> struct store< expression > : rearrange {}; - // clang-format on + // select which rules in the grammar will produce parse tree nodes: + + template< typename Rule > + using selector = parse_tree::selector< + Rule, + parse_tree::apply_store_content::to< + integer, + variable >, + parse_tree::apply_remove_content::to< + plus, + minus, + multiply, + divide >, + parse_tree::apply< rearrange >::to< + product, + expression > >; // debugging/show result: @@ -126,7 +121,7 @@ for( int i = 1; i < argc; ++i ) { try { argv_input<> in( argv, i ); - if( const auto root = parse_tree::parse< example::grammar, example::store >( in ) ) { + if( const auto root = parse_tree::parse< example::grammar, example::selector >( in ) ) { example::print_node( *root ); } else { diff -Nru tao-pegtl-2.7.0/src/test/pegtl/ascii_forty_two.cpp tao-pegtl-2.7.1/src/test/pegtl/ascii_forty_two.cpp --- tao-pegtl-2.7.0/src/test/pegtl/ascii_forty_two.cpp 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/src/test/pegtl/ascii_forty_two.cpp 2018-10-02 14:31:17.000000000 +0000 @@ -0,0 +1,42 @@ +// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" +#include "verify_analyze.hpp" +#include "verify_rule.hpp" + +namespace tao +{ + namespace TAO_PEGTL_NAMESPACE + { + void unit_test() + { + verify_analyze< forty_two< 'a' > >( __LINE__, __FILE__, true, false ); + verify_analyze< forty_two< 'a', 'z' > >( __LINE__, __FILE__, true, false ); + + for( std::size_t i = 0; i < 42; ++i ) { + verify_rule< forty_two< 'a' > >( __LINE__, __FILE__, std::string( i, 'a' ), result_type::LOCAL_FAILURE ); + } + for( std::size_t i = 42; i < 100; ++i ) { + verify_rule< forty_two< 'a' > >( __LINE__, __FILE__, std::string( i, 'a' ), result_type::SUCCESS, i - 42 ); + } + for( std::size_t i = 0; i < 42; ++i ) { + verify_rule< forty_two< 'a', 'z' > >( __LINE__, __FILE__, std::string( i, 'a' ), result_type::LOCAL_FAILURE ); + } + for( std::size_t i = 42; i < 100; ++i ) { + verify_rule< forty_two< 'a', 'z' > >( __LINE__, __FILE__, std::string( i, 'a' ), result_type::SUCCESS, i - 42 ); + } + for( std::size_t i = 0; i < 42; ++i ) { + verify_rule< forty_two< 'a', 'z' > >( __LINE__, __FILE__, std::string( i, 'z' ), result_type::LOCAL_FAILURE ); + } + for( std::size_t i = 42; i < 100; ++i ) { + verify_rule< forty_two< 'a', 'z' > >( __LINE__, __FILE__, std::string( i, 'z' ), result_type::SUCCESS, i - 42 ); + } + verify_rule< forty_two< 'a', 'z' > >( __LINE__, __FILE__, "azzaazaazaaazzzaaaazzaaazzaazazzzaazzazaza", result_type::SUCCESS ); + } + + } // namespace TAO_PEGTL_NAMESPACE + +} // namespace tao + +#include "main.hpp" diff -Nru tao-pegtl-2.7.0/src/test/pegtl/CMakeLists.txt tao-pegtl-2.7.1/src/test/pegtl/CMakeLists.txt --- tao-pegtl-2.7.0/src/test/pegtl/CMakeLists.txt 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/src/test/pegtl/CMakeLists.txt 2018-10-02 14:31:17.000000000 +0000 @@ -9,6 +9,7 @@ ascii_classes.cpp ascii_eol.cpp ascii_eolf.cpp + ascii_forty_two.cpp ascii_identifier.cpp ascii_istring.cpp ascii_keyword.cpp @@ -18,7 +19,9 @@ ascii_two.cpp contrib_alphabet.cpp contrib_integer.cpp + contrib_if_then.cpp contrib_json.cpp + contrib_parse_tree.cpp contrib_raw_string.cpp contrib_rep_one_min_max.cpp contrib_to_string.cpp @@ -99,6 +102,7 @@ endif () get_filename_component (exename ${testsourcefile} NAME_WE) + set (exename "pegtl-test-${exename}") add_executable (${exename} ${testsourcefile}) target_link_libraries (${exename} PRIVATE taocpp::pegtl) set_target_properties (${exename} PROPERTIES diff -Nru tao-pegtl-2.7.0/src/test/pegtl/contrib_if_then.cpp tao-pegtl-2.7.1/src/test/pegtl/contrib_if_then.cpp --- tao-pegtl-2.7.0/src/test/pegtl/contrib_if_then.cpp 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/src/test/pegtl/contrib_if_then.cpp 2018-10-02 14:31:17.000000000 +0000 @@ -0,0 +1,31 @@ +// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" +#include "verify_rule.hpp" + +#include + +namespace tao +{ + namespace TAO_PEGTL_NAMESPACE + { + void unit_test() + { + // clang-format off + using grammar = + if_then< one< 'a' >, one< 'b' >, one< 'c' > >:: + else_if_then< one< 'a' >, one< 'b' > >:: + else_then< one< 'c' > >; + + verify_rule< grammar >( __LINE__, __FILE__, "abc", result_type::SUCCESS, 0 ); + verify_rule< grammar >( __LINE__, __FILE__, "abcd", result_type::SUCCESS, 1 ); + verify_rule< grammar >( __LINE__, __FILE__, "ab", result_type::LOCAL_FAILURE, 2 ); + verify_rule< grammar >( __LINE__, __FILE__, "c", result_type::SUCCESS, 0 ); + } + + } // namespace TAO_PEGTL_NAMESPACE + +} // namespace tao + +#include "main.hpp" diff -Nru tao-pegtl-2.7.0/src/test/pegtl/contrib_parse_tree.cpp tao-pegtl-2.7.1/src/test/pegtl/contrib_parse_tree.cpp --- tao-pegtl-2.7.0/src/test/pegtl/contrib_parse_tree.cpp 1970-01-01 00:00:00.000000000 +0000 +++ tao-pegtl-2.7.1/src/test/pegtl/contrib_parse_tree.cpp 2018-10-02 14:31:17.000000000 +0000 @@ -0,0 +1,60 @@ +// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" + +#include + +namespace tao +{ + namespace TAO_PEGTL_NAMESPACE + { + // clang-format off + struct A : one< 'a' > {}; + struct B : one< 'b' > {}; + struct C : one< 'c' > {}; + + struct D : sor< seq< A, B >, seq< A, C > > {}; + // clang-format on + + template< typename Rule > + struct selector + : parse_tree::selector< Rule, parse_tree::apply_store_content::to< A, B, C, D > > + { + }; + + void unit_test() + { + memory_input<> in( "ac", "input" ); + const auto r = parse_tree::parse< D, selector >( in ); + TAO_PEGTL_TEST_ASSERT( r->is_root() ); + TAO_PEGTL_TEST_ASSERT( !r->has_content() ); + TAO_PEGTL_TEST_ASSERT( r->children.size() == 1 ); + + const auto& d = r->children.front(); + TAO_PEGTL_TEST_ASSERT( !d->is_root() ); + TAO_PEGTL_TEST_ASSERT( d->id == &typeid( D ) ); + TAO_PEGTL_TEST_ASSERT( d->is< D >() ); +#if !defined( _MSC_VER ) + TAO_PEGTL_TEST_ASSERT( d->name() == "tao::pegtl::D" ); +#endif + + TAO_PEGTL_TEST_ASSERT( d->has_content() ); + TAO_PEGTL_TEST_ASSERT( d->begin().byte == 0 ); + TAO_PEGTL_TEST_ASSERT( d->end().byte == 2 ); + TAO_PEGTL_TEST_ASSERT( d->content() == "ac" ); + + TAO_PEGTL_TEST_ASSERT( d->children.size() == 2 ); + TAO_PEGTL_TEST_ASSERT( d->children.front()->is< A >() ); + TAO_PEGTL_TEST_ASSERT( d->children.back()->is< C >() ); + + memory_input<> in2( "x", "input" ); + const auto r2 = parse_tree::parse< D, selector >( in2 ); + TAO_PEGTL_TEST_ASSERT( !r2 ); + } + + } // namespace TAO_PEGTL_NAMESPACE + +} // namespace tao + +#include "main.hpp" diff -Nru tao-pegtl-2.7.0/.travis.yml tao-pegtl-2.7.1/.travis.yml --- tao-pegtl-2.7.0/.travis.yml 2018-07-31 19:00:26.000000000 +0000 +++ tao-pegtl-2.7.1/.travis.yml 2018-10-02 14:31:17.000000000 +0000 @@ -187,7 +187,7 @@ - CXX=clang++ - os: osx - osx_image: xcode9.3 + osx_image: xcode9.4 compiler: clang env: - CXX=clang++