linking errors while separate parser using boost spirit x3

前端 未结 2 1453
独厮守ぢ
独厮守ぢ 2020-12-10 20:53

I am currentyl trying to separate my boost spirit x3 parser into different _def and .cpp files using BOOST_SPIRIT_DEFINE/DECLARE/INSTANTIATE, but I keep getting

2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-10 21:23

    Two points:

    1. You define the context as

      typedef x3::phrase_parse_context::type context_type;
      

      However, you try to invoke it with x3::space instead of x3::ascii::space.

      The hint was in the error message that you didn't include:

      /home/sehe/custom/boost/boost/spirit/home/x3/nonterminal/rule.hpp:116: undefined reference to 'bool kyle::parser::impl::parse_rule<__gnu_cxx::__normal_iterator, std::allocator > >, boost::spirit::x3::context const, boost::spirit::x3::unused_type>, std::__cxx11::basic_string, std::allocator > >(boost::spirit::x3::rule, std::allocator >, false>, __gnu_cxx::__normal_iterator, std::allocator > >&, __gnu_cxx::__normal_iterator, std::allocator > > const&, boost::spirit::x3::contextchar_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, std::__cxx11::basic_string, std::allocator >&)'

    2. Iterator type is getting deduced as std::string::iterator, not std::string::const_iterator. Fix it or don't use auto always:

    Live On Melpon

    FULL CODE

    For posterity

    • config.hpp:

      #include 
      
      namespace kyle{
          namespace parser{
      
              namespace x3 = boost::spirit::x3;
      
              typedef std::string::const_iterator iterator_type;
              typedef x3::phrase_parse_context::type context_type;
      
          }
      }
      
    • literals.cpp:

      #include "literals_def.hpp"
      #include "config.hpp"
      #include 
      
      namespace kyle { namespace parser { namespace impl {
          BOOST_SPIRIT_INSTANTIATE(identifier_type, iterator_type, context_type);
      } } }
      
    • literals_def.hpp:

      #include 
      #include "literals.hpp"
      
      namespace kyle {
          namespace parser {
              namespace impl {
      
                  namespace x3 = boost::spirit::x3;
      
                  const identifier_type identifier = "identifier";
                  auto const identifier_def = x3::alpha >> *x3::alnum;
      
                  BOOST_SPIRIT_DEFINE(identifier)
              }
              impl::identifier_type identifier(){
                  return impl::identifier;
              }
          }
      }
      
    • literals.hpp:

      #include 
      
      namespace kyle{
          namespace parser{
              namespace impl {
                  namespace x3 = boost::spirit::x3;
      
                  struct identifier_class;
      
                  typedef x3::rule identifier_type;
      
                  BOOST_SPIRIT_DECLARE(identifier_type)
              }
      
              impl::identifier_type identifier();
          }
      }
      
    • main.cpp:

      #include "literals.hpp"
      #include 
      
      template
      bool test(std::string const& str, Parser p, std::string& output, bool full_match = true)
      {
          auto in = str.begin();
          auto end = str.end();
          bool ret = boost::spirit::x3::phrase_parse(in, end, p, boost::spirit::x3::space, output);
          ret &= (!full_match || (in == end));
          return ret;
      }
      
      int main(){
          std::string s;
          auto b = test("fobar", kyle::parser::identifier(), s);
          std::cout << b << ": " << s << std::endl;
      }
      
    • CMakeLists.txt:

      ADD_EXECUTABLE(sox3 main.cpp literals.cpp)
      
      SET(CMAKE_CXX_COMPILER g++-5)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /home/sehe/custom/boost -std=c++14 -O3 -pthread -march=native -flto)
      

提交回复
热议问题