taocpp / PEGTL

Parsing Expression Grammar Template Library
Boost Software License 1.0
1.94k stars 228 forks source link

Compilation Failure: Parsing Rule `minus` Breaks Tree Creation #141

Closed sanssecours closed 5 years ago

sanssecours commented 5 years ago

Steps to Reproduce the Issue

  1. Download the following archive: Parse Tree Selector.zip
  2. Extract the directory stored in the archive (Parse Tree Selector) somewhere
  3. Change into the directory Parse Tree Selector
  4. Run make

Expected Result

Make should be able to compile the file yaypeg.cpp.

Actual Result

The compiler (Clang on my machine) fails to compile the code printing the following error message:

[1/2] Building CXX object CMakeFiles/yaypeg.dir/Source/yaypeg.cpp.o
FAILED: CMakeFiles/yaypeg.dir/Source/yaypeg.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++   -I/usr/local/include -std=gnu++1z -MD -MT CMakeFiles/yaypeg.dir/Source/yaypeg.cpp.o -MF CMakeFiles/yaypeg.dir/Source/yaypeg.cpp.o.d -o CMakeFiles/yaypeg.dir/Source/yaypeg.cpp.o -c ../Source/yaypeg.cpp
In file included from ../Source/yaypeg.cpp:4:
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:108:24: error: no viable overloaded '='
               m_begin = in.iterator();
               ~~~~~~~ ^ ~~~~~~~~~~~~~
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:301:42: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::basic_node<tao::pegtl::parse_tree::node>::start<tao::pegtl::ascii::one<'t'>, tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
                  state.back()->template start< Rule >( in, st... );
                                         ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:61:33: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::internal::make_control<tao::pegtl::parse_tree::node, selector, normal>::control<tao::pegtl::ascii::one<'t'>, true, true>::start<tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
               Control< Rule >::start( static_cast< const Input& >( in ), st... );
                                ^
/usr/local/include/tao/pegtl/contrib/../normal.hpp:82:80: note: in instantiation of function template specialization 'tao::pegtl::internal::duseltronik<tao::pegtl::ascii::one<'t'>, tao::pegtl::apply_mode::NOTHING, tao::pegtl::rewind_mode::ACTIVE, nothing, type, tao::pegtl::dusel_mode::CONTROL>::match<tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
            return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... );
                                                                               ^
/usr/local/include/tao/pegtl/internal/minus.hpp:51:44: note: in instantiation of function template specialization 'tao::pegtl::normal<tao::pegtl::ascii::one<'t'> >::match<tao::pegtl::apply_mode::NOTHING, tao::pegtl::rewind_mode::ACTIVE, nothing, type, tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
               if( !Control< S >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( i2, st... ) ) {
                                           ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:38:38: note: in instantiation of function template specialization 'tao::pegtl::internal::minus<tao::pegtl::ascii::any, tao::pegtl::ascii::one<'t'> >::match<tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
               return Rule::template match< A, M, Action, Control >( in, st... );
                                     ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:63:85: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
                                                                                    ^
/usr/local/include/tao/pegtl/contrib/../normal.hpp:82:80: note: in instantiation of function template specialization 'tao::pegtl::internal::duseltronik<not_t, tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::dusel_mode::CONTROL>::match<tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
            return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... );
                                                                               ^
/usr/local/include/tao/pegtl/contrib/../parse.hpp:56:43: note: in instantiation of function template specialization 'tao::pegtl::normal<not_t>::match<tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
         return Control< Rule >::template match< A, M, Action, Control >( in, st... );
                                          ^
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:437:39: note: in instantiation of function template specialization 'tao::pegtl::parse<not_t, nothing, internal::make_control<node, selector, normal>::type, tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
            if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st... ) ) {
                                      ^
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:452:20: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::parse<not_t, tao::pegtl::parse_tree::node, selector, nothing, normal, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
            return parse< Rule, node, Selector, Action, Control >( in, st... );
                   ^
../Source/yaypeg.cpp:16:27: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::parse<not_t, selector, nothing, normal, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
  auto root = parse_tree::parse<not_t, selector>(input);
                          ^
/usr/local/include/tao/pegtl/contrib/../internal/iterator.hpp:39:23: note: candidate function not viable: no known conversion from 'const tao::pegtl::internal::memory_input_base<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>::iterator_t' (aka 'const char *const') to 'const tao::pegtl::internal::iterator' for 1st argument
            iterator& operator=( const iterator& ) = default;
                      ^
/usr/local/include/tao/pegtl/contrib/../internal/iterator.hpp:40:23: note: candidate function not viable: no known conversion from 'const tao::pegtl::internal::memory_input_base<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>::iterator_t' (aka 'const char *const') to 'tao::pegtl::internal::iterator' for 1st argument
            iterator& operator=( iterator&& ) = default;
                      ^
In file included from ../Source/yaypeg.cpp:4:
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:115:22: error: no viable overloaded '='
               m_end = in.iterator();
               ~~~~~ ^ ~~~~~~~~~~~~~
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:311:31: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::basic_node<tao::pegtl::parse_tree::node>::success<tao::pegtl::ascii::one<'t'>, tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
                  n->template success< Rule >( in, st... );
                              ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:64:36: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::internal::make_control<tao::pegtl::parse_tree::node, selector, normal>::control<tao::pegtl::ascii::one<'t'>, true, true>::success<tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
                  Control< Rule >::success( static_cast< const Input& >( in ), st... );
                                   ^
/usr/local/include/tao/pegtl/contrib/../normal.hpp:82:80: note: in instantiation of function template specialization 'tao::pegtl::internal::duseltronik<tao::pegtl::ascii::one<'t'>, tao::pegtl::apply_mode::NOTHING, tao::pegtl::rewind_mode::ACTIVE, nothing, type, tao::pegtl::dusel_mode::CONTROL>::match<tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
            return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... );
                                                                               ^
/usr/local/include/tao/pegtl/internal/minus.hpp:51:44: note: in instantiation of function template specialization 'tao::pegtl::normal<tao::pegtl::ascii::one<'t'> >::match<tao::pegtl::apply_mode::NOTHING, tao::pegtl::rewind_mode::ACTIVE, nothing, type, tao::pegtl::memory_input<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>>' requested here
               if( !Control< S >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( i2, st... ) ) {
                                           ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:38:38: note: in instantiation of function template specialization 'tao::pegtl::internal::minus<tao::pegtl::ascii::any, tao::pegtl::ascii::one<'t'> >::match<tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
               return Rule::template match< A, M, Action, Control >( in, st... );
                                     ^
/usr/local/include/tao/pegtl/internal/duseltronik.hpp:63:85: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
                                                                                    ^
/usr/local/include/tao/pegtl/contrib/../normal.hpp:82:80: note: in instantiation of function template specialization 'tao::pegtl::internal::duseltronik<not_t, tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::dusel_mode::CONTROL>::match<tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
            return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... );
                                                                               ^
/usr/local/include/tao/pegtl/contrib/../parse.hpp:56:43: note: in instantiation of function template specialization 'tao::pegtl::normal<not_t>::match<tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, nothing, type, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf>>' requested here
         return Control< Rule >::template match< A, M, Action, Control >( in, st... );
                                          ^
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:437:39: note: in instantiation of function template specialization 'tao::pegtl::parse<not_t, nothing, internal::make_control<node, selector, normal>::type, tao::pegtl::apply_mode::ACTION, tao::pegtl::rewind_mode::REQUIRED, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
            if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st... ) ) {
                                      ^
/usr/local/include/tao/pegtl/contrib/parse_tree.hpp:452:20: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::parse<not_t, tao::pegtl::parse_tree::node, selector, nothing, normal, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
            return parse< Rule, node, Selector, Action, Control >( in, st... );
                   ^
../Source/yaypeg.cpp:16:27: note: in instantiation of function template specialization 'tao::pegtl::parse_tree::parse<not_t, selector, nothing, normal, tao::pegtl::file_input<tao::pegtl::tracking_mode::IMMEDIATE, tao::pegtl::ascii::eol::lf_crlf> &>' requested here
  auto root = parse_tree::parse<not_t, selector>(input);
                          ^
/usr/local/include/tao/pegtl/contrib/../internal/iterator.hpp:39:23: note: candidate function not viable: no known conversion from 'const tao::pegtl::internal::memory_input_base<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>::iterator_t' (aka 'const char *const') to 'const tao::pegtl::internal::iterator' for 1st argument
            iterator& operator=( const iterator& ) = default;
                      ^
/usr/local/include/tao/pegtl/contrib/../internal/iterator.hpp:40:23: note: candidate function not viable: no known conversion from 'const tao::pegtl::internal::memory_input_base<tao::pegtl::tracking_mode::LAZY, tao::pegtl::ascii::eol::lf_crlf, const char *>::iterator_t' (aka 'const char *const') to 'tao::pegtl::internal::iterator' for 1st argument
            iterator& operator=( iterator&& ) = default;
                      ^
2 errors generated.

.

Additional Information

It seems the rule minus causes problems. At least everything works fine if I replace

struct not_t : minus<any, one<'t'>> {};

with the code:

struct not_t : seq<not_at<one<'t'>>, any> {};

in yaypeg.cpp:

#include <string>

#include <tao/pegtl.hpp>
#include <tao/pegtl/contrib/parse_tree.hpp>

using namespace tao::pegtl;

struct not_t : minus<any, one<'t'>> {};

template <typename Rule> struct selector : std::true_type {};

int main(int argc, char *argv[]) {
  std::string filename = argv[1];
  file_input<> input{filename};

  auto root = parse_tree::parse<not_t, selector>(input);

  return 0;
}

.

System Information

d-frey commented 5 years ago

@ColinH I could "fix" the issue by changing m_begin = in.iterator(); to m_begin = TAO_PEGTL_NAMESPACE::internal::iterator( in.iterator() ); (and likewise for m_end) in parse_tree.hpp, but I wonder if that is the correct solution. Looking at minus: i2 always uses tracking_mode::lazy. Is this the right thing to do here?

ColinH commented 5 years ago

In minus, the input i2 uses tracking_mode::lazy because it is used with apply_mode::nothing.

(When actions are disabled, usually the only place that the location is needed is for a global failure, an exception, which usually terminates the parsing run; tracking_mode::eager usually only makes sense when the location is accessed in multiple places.)

d-frey commented 5 years ago

I guess the parse tree is then still supposed to contain the nodes of at<...> and hence I will commit my initial fix and leave minus as is.