问题描述
我是currentyl,试图使用BOOST_SPIRIT_DEFINE/DECLARE/INSTANTIATE
将我的boost spirit x3解析器分成不同的_def和.cpp文件,但是我一直收到链接错误.这里是我的解析器,它是分开的.
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.
读取链接器错误
<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:
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:
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:
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:
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:
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;
}
推荐答案
两点:
-
您将上下文定义为
You define the context as
typedef x3::phrase_parse_context<x3::space_type>::type context_type;
但是,您尝试使用x3::space
而不是x3::ascii::space
来调用它.
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:
迭代器类型被推导为std::string::iterator
,而不是std::string::const_iterator
.修复它或不总是使用auto
:
Iterator type is getting deduced as std::string::iterator
, not std::string::const_iterator
. Fix it or don't use auto
always:
后代
-
config.hpp:
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::space_type>::type context_type;
}
}
literals.cpp:
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:
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:
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:
main.cpp:
#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;
}
CMakeLists.txt:
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)
这篇关于使用Boost Spirit x3在单独的解析器中链接错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!