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 a linking error.
HERE is my parser which is separated.
The linker error reads
<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&)'
What am I doing wrong? How can I make my example work?
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; }