使用boost spirit x3

时间:2016-11-08 21:03:10

标签: c++ boost-spirit linker-errors boost-spirit-x3

我是currentyl尝试使用BOOST_SPIRIT_DEFINE/DECLARE/INSTANTIATE将我的提升精神x3解析器分成不同的_def和.cpp文件,但我一直收到链接错误。 HERE是我的解析器,它是分开的。

链接器错误读取

<artificial>:(.text.startup+0xbb): undefined reference to `bool kyle::parser::impl::parse_rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type>, boost::spirit::x3::unused_type const>(boost::spirit::x3::rule<kyle::parser::impl::identifier_class, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, false>, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, boost::spirit::x3::unused_type const&)'

我做错了什么?我怎样才能使我的例子有效?

  • config.hpp:

    #include <boost/spirit/home/x3.hpp>
    
    namespace kyle{
    namespace parser{
    
    namespace x3 = boost::spirit::x3;
    
    typedef std::string::const_iterator iterator_type;
    typedef x3::phrase_parse_context<x3::ascii::space_type>::type context_type;
    
    }
    }
    
  • literals.cpp:

    #include "literals_def.hpp"
    #include "config.hpp"
    #include <boost/spirit/home/x3.hpp>
    
    
    namespace kyle {
    namespace parser {
    namespace impl {
    
    BOOST_SPIRIT_INSTANTIATE(identifier_type, iterator_type, context_type);
    
    }
    }
    }
    
  • literals_def.hpp:

    #include <boost/spirit/home/x3.hpp>
    #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 <boost/spirit/home/x3.hpp>
    
    namespace kyle{
    namespace parser{
    namespace impl {
    namespace x3 = boost::spirit::x3;
    
    struct identifier_class;
    
    typedef x3::rule<identifier_class, std::string> identifier_type;
    
    BOOST_SPIRIT_DECLARE(identifier_type)
    }
    
    impl::identifier_type identifier();
    
    
    }
    }
    
  • main.cpp:

    #include "literals.hpp"
    #include <iostream>
    
    template<typename Parser>
    bool test(std::string str, Parser&& p, 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);
        ret &= (!full_match || (in == end));
        return ret;
    
    }
    
    int main(){
        auto b = test("fobar", kyle::parser::identifier());
        std::cout << b << std::endl;
    
    }
    

2 个答案:

答案 0 :(得分:6)

两点:

  1. 您将上下文定义为

    foreign_key_constraint/3

    但是,您尝试使用typedef x3::phrase_parse_context<x3::space_type>::type context_type; 而不是x3::space来调用它。

    提示位于您未包含的错误消息中:

      

    x3::ascii::space /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<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(boost::spirit::x3::rule<kyle::parser::impl::identifier_class, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, false>, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit:: char_encoding::standard

  2. 迭代器类型被推断为, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)',而不是std::string::iterator。修复它或不要始终使用std::string::const_iterator

  3. <强> Live On Melpon

    完整代码

    为后代

    • config.hpp:

      auto
    • literals.cpp:

      #include <boost/spirit/home/x3.hpp>
      
      namespace kyle{
          namespace parser{
      
              namespace x3 = boost::spirit::x3;
      
              typedef std::string::const_iterator iterator_type;
              typedef x3::phrase_parse_context<x3::space_type>::type context_type;
      
          }
      }
      
    • literals_def.hpp:

      #include "literals_def.hpp"
      #include "config.hpp"
      #include <boost/spirit/home/x3.hpp>
      
      namespace kyle { namespace parser { namespace impl {
          BOOST_SPIRIT_INSTANTIATE(identifier_type, iterator_type, context_type);
      } } }
      
    • literals.hpp:

      #include <boost/spirit/home/x3.hpp>
      #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;
              }
          }
      }
      
    • main.cpp:

      #include <boost/spirit/home/x3.hpp>
      
      namespace kyle{
          namespace parser{
              namespace impl {
                  namespace x3 = boost::spirit::x3;
      
                  struct identifier_class;
      
                  typedef x3::rule<identifier_class, std::string> identifier_type;
      
                  BOOST_SPIRIT_DECLARE(identifier_type)
              }
      
              impl::identifier_type identifier();
          }
      }
      
    • CMakeLists.txt:

      #include "literals.hpp"
      #include <iostream>
      
      template<typename Parser>
      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;
      }
      

答案 1 :(得分:4)

除了回答之外,我还要补充一点:

您需要对您声明的内容和实际使用内容非常准确。 X3允许任何类型的可能类型,但链接器不允许。

这里有一个提示:当发生链接器错误时,在BOOST_SPIRIT_INSTANTIATE之后,声明如下内容:

int x = context_type{};

这将是一个错误,是的,因为context_type无法转换为int。但是,该错误也会为您提供上下文的确切类型。将它与链接器错误进行比较,您将看到错误。