链接错误,同时使用boost spirit x3单独分析器(linking errors while separate parser using boost spirit x3)

编程入门 行业动态 更新时间:2024-10-25 08:22:28
链接错误,同时使用boost spirit x3单独分析器(linking errors while separate parser using boost spirit x3)

我是currentyl尝试使用BOOST_SPIRIT_DEFINE/DECLARE/INSTANTIATE将我的boost spirit x3解析器分隔成不同的_def和.cpp文件,但我不断收到链接错误。 这是我的解析器,它是分开的。

链接器错误读取

<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; }

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; }

最满意答案

两点:

您将上下文定义为

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:: /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 , 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 。 修复它或不总是使用auto :

生活在Melpon

完整的代码

为后人

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:

#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 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)

Two points:

You define the context as

typedef x3::phrase_parse_context<x3::space_type>::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<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, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'

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 <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:

#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 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)

更多推荐

本文发布于:2023-04-28 02:59:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1329823.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:分析器   错误   链接   spirit   boost

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!