本文介绍了使用Boost Spirit x3在单独的解析器中链接错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  • 推荐答案

    两点:

    1. 您将上下文定义为

    1. 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在单独的解析器中链接错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    09-05 08:20