gpt4 book ai didi

c++ - Boost spirit x3 解析器在解析时抛出 std::logic_error

转载 作者:行者123 更新时间:2023-11-30 03:36:30 28 4
gpt4 key购买 nike

我使用 boost spirit x3 创建了一个语法。在测试我生成的解析器时,我认识到存在解析器抛出以下异常的情况:

terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid

我不知道使用 boost spirit x3 会发生这种情况,我认为解析方法 eighter 返回 false 或抛出 boost::spirit::x3::expectation_failure,我做错了什么语法,因为这不应该发生在这里。我上传了我的 mcve HERE ,如果您执行二进制文件,则会抛出 std::logic 错误。

  • 例子.cpp

    #include "example_def.hpp"
    #include "config.hpp"

    namespace client { namespace parser {

    BOOST_SPIRIT_INSTANTIATE(var_dec_type, iterator_type, context_type)

    }}
  • main.cpp

    #include <iostream>
    //#define SINGLE_TU
    #if defined(SINGLE_TU)
    #pragma message "yesdef(SINGLE_TU)"
    #else
    #pragma message "notdef(SINGLE_TU)"
    #endif
    #ifdef SINGLE_TU
    #include "types_def.hpp"
    #include "example_def.hpp"
    #else
    #include "example.hpp"
    #endif

    template<typename Parser, typename Attribute>
    bool test(const std::string& str, Parser&& p, Attribute&& attr)
    {
    using iterator_type = std::string::const_iterator;
    iterator_type in = str.begin();
    iterator_type end = str.end();

    bool ret = boost::spirit::x3::phrase_parse(in, end, p, boost::spirit::x3::ascii::space, attr);
    ret &= (in == end);
    return ret;

    }

    int main()
    {
    client::ast::VariableDec attr;

    std::cout << test("var foo : foo<bar, baz<bahama>>", client::var_dec() , attr);
    return 0;
    }
  • 类型.cpp

    #include "config.hpp"
    #include "types_def.hpp"
    #include <iostream>

    namespace client {namespace parser {

    BOOST_SPIRIT_INSTANTIATE(type_type, iterator_type, context_type);

    BOOST_SPIRIT_INSTANTIATE(class_type_type, iterator_type, context_type);
    #define PARSE_RULE_BODY
    #if defined(PARSE_RULE_BODY)
    #pragma message "yesdef(PARSE_RULE_BODY)"
    //This causes the parse_rule generated by
    //BOOST_SPIRIT_DEFINE for type
    //to *not* be used.
    #include <boost/fusion/iterator/deref.hpp>
    #else
    #pragma message "notdef(PARSE_RULE_BODY)"
    //This causes the parse_rule generated by
    //BOOST_SPIRIT_DEFINE for type
    //to be used.
    #endif
    #define SEHE_TYPES_DEF_HPP_PASTE
    #define EXPLICT_SPECIALIZATION_FROM_LINKER_ERROR_MSG
    #if defined(SEHE_TYPES_DEF_HPP_PASTE)
    #pragma message "yesdef(SEHE_TYPES_DEF_HPP_PASTE)"
    //Source:
    // The following code was copy&pasted&reformatted from lines 38-53 of:
    // https://github.com/sehe/linker_error_example/blob/explicit_instantiation/types_def.hpp
    // on about 2016-11-15.
    // with minor modifications:
    // * reformatting
    // * Added body with:
    // * printing first..last.
    //=======================
    namespace {
    template <typename Seq, size_t N>
    using field_at =
    boost::fusion::basic_iterator
    < boost::fusion::struct_iterator_tag
    , boost::fusion::random_access_traversal_tag
    , Seq
    , N
    >;
    template <typename Seq, size_t N, size_t M>
    using fields =
    boost::fusion::iterator_range<field_at<Seq, N>, field_at<Seq, M> >;
    using Attributes =
    fields<client::ast::VariableDec, 1, 2>;
    using Context =
    x3::context
    < x3::skipper_tag
    , x3::char_class<boost::spirit::char_encoding::ascii, x3::space_tag> const
    , x3::unused_type
    >;
    }
    template
    #ifdef PARSE_RULE_BODY
    <>
    #endif
    bool parse_rule
    < std::string::const_iterator
    , Context
    , Attributes
    >(
    decltype(type) rule,
    std::string::const_iterator &first,
    std::string::const_iterator const &last,
    Context const &context,
    Attributes &attr)
    #ifndef PARSE_RULE_BODY
    ;
    #else
    {
    std::cout<<"***in function="<<__func__<<"\n";
    std::string::const_iterator beg=first;
    std::cout<<":input=\n{";
    for(; beg!=last; ++beg) std::cout<<*beg;
    std::cout<<"}\n";
    using required_t=type_type::attribute_type;
    required_t required_v=boost::fusion::deref(attr.first);
    //attr type required by parse_rule generated by:
    // BOOST_SPIRIT_INSTANTIATE(type_type, iterator_type, context_type)
    ;
    bool result=parse_rule(rule,first,last,context,required_v)
    //This should call the parse_rule generated by:
    // BOOST_SPIRIT_INSTANTIATE(type_type, iterator_type, context_type)
    ;
    std::cout<<":result="<<result<<"\n";
    return result;
    }
    #endif

    #elif defined(EXPLICT_SPECIALIZATION_FROM_LINKER_ERROR_MSG)
    #pragma message "yesdef(EXPLICT_SPECIALIZATION_FROM_LINKER_ERROR_MSG)"
    template
    #ifdef PARSE_RULE_BODY
    <>
    #endif
    //The following simply copied&pasted from an earlier linker error
    //message, and then reformatted to clarify what
    //was being specialized.
    bool
    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::ascii
    , boost::spirit::x3::space_tag
    > const
    , boost::spirit::x3::unused_type
    >
    , boost::fusion::iterator_range
    < boost::fusion::basic_iterator
    < boost::fusion::struct_iterator_tag
    , boost::fusion::random_access_traversal_tag
    , client::ast::VariableDec
    , 1
    >
    , boost::fusion::basic_iterator
    < boost::fusion::struct_iterator_tag
    , boost::fusion::random_access_traversal_tag
    , client::ast::VariableDec
    , 2
    >
    >
    >
    ( boost::spirit::x3::rule//==decltype(type) where types from types_def.hpp:16
    < client::parser::type_class//types.hpp:15
    , boost::spirit::x3::variant
    < client::ast::nil
    , boost::spirit::x3::forward_ast
    < client::ast::LambdaType
    >
    , boost::spirit::x3::forward_ast
    < client::ast::ClassType
    >
    >
    , false
    >
    , __gnu_cxx::__normal_iterator//==std::string::const_iterator
    < char const*
    , std::__cxx11::basic_string
    < char
    , std::char_traits<char>
    , std::allocator<char>
    >
    >& first
    , __gnu_cxx::__normal_iterator//==std::string::const_iterator
    < char const*
    , std::__cxx11::basic_string
    < char
    , std::char_traits<char>
    , std::allocator<char>
    >
    > const& last
    , boost::spirit::x3::context//=?Context from #if defined(SEHE_TYPES_DEF_HPP_PASTE)
    < boost::spirit::x3::skipper_tag
    , boost::spirit::x3::char_class
    < boost::spirit::char_encoding::ascii
    , boost::spirit::x3::space_tag
    > const
    , boost::spirit::x3::unused_type
    > const& context
    , boost::fusion::iterator_range//=?Attributes from #if defined(SEHE_TYPES_DEF_HPP_PASTE)
    < boost::fusion::basic_iterator
    < boost::fusion::struct_iterator_tag
    , boost::fusion::random_access_traversal_tag
    , client::ast::VariableDec
    , 1
    >
    , boost::fusion::basic_iterator
    < boost::fusion::struct_iterator_tag
    , boost::fusion::random_access_traversal_tag
    , client::ast::VariableDec
    , 2
    >
    >& attr
    )
    #ifndef PARSE_RULE_BODY
    ;
    #else
    {
    std::cout<<"***in function="<<__func__<<"\n";
    std::string::const_iterator beg=first;
    std::cout<<":input=\n{";
    for(; beg!=last; ++beg) std::cout<<*beg;
    std::cout<<"}\n";
    return false;
    }
    #endif//PARSE_RULE_BODY
    #endif//(SEHE_TYPES_DEF_HPP_PASTE)
    }}
  • ast.hpp

    //
    // Created by lukas on 11.11.16.
    //

    #ifndef LINKER_ERROR_EXAMPLE_AST_HPP_HPP
    #define LINKER_ERROR_EXAMPLE_AST_HPP_HPP

    #include <boost/fusion/adapted/struct.hpp>
    #include <boost/spirit/home/x3.hpp>
    #include <boost/spirit/home/x3/support/ast/variant.hpp>

    #include <vector>
    #include <string>

    namespace client { namespace ast {

    namespace x3 = boost::spirit::x3;

    struct LambdaType;
    struct ClassType;
    struct nil{};

    typedef x3::variant <
    nil,
    x3::forward_ast<LambdaType>,
    x3::forward_ast<ClassType>
    > Type;

    struct LambdaType {
    std::vector<Type> parameters_;
    Type return_type_;
    };

    struct ClassType {
    std::vector<std::string> name_;
    std::vector<Type> template_args_;
    };

    struct VariableDec {
    std::string _name;
    Type _type;
    };


    }}

    BOOST_FUSION_ADAPT_STRUCT(client::ast::LambdaType, parameters_, return_type_)
    BOOST_FUSION_ADAPT_STRUCT(client::ast::ClassType, name_, template_args_)
    BOOST_FUSION_ADAPT_STRUCT(client::ast::VariableDec, _name, _type)

    #endif //LINKER_ERROR_EXAMPLE_AST_HPP_HPP
  • 配置.hpp

    #ifndef LINKER_ERROR_EXAMPLE_CONFIG_HPP
    #define LINKER_ERROR_EXAMPLE_CONFIG_HPP

    #include <boost/spirit/home/x3.hpp>

    namespace client{
    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;

    }
    }

    #endif //LINKER_ERROR_EXAMPLE_CONFIG_HPP
  • example_def.hpp

    #ifndef LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP
    #define LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP

    #include "ast.hpp"
    #include "example.hpp"
    #include "types.hpp"

    namespace client { namespace parser {

    #ifndef SINGLE_TU
    namespace { const auto& type = client::type(); }
    #endif

    const var_dec_type var_dec = "var_dec";

    #define EXAMPLE_DEF_LINK_ERR
    #if defined(EXAMPLE_DEF_LINK_ERR)
    #pragma message "yesdef(EXAMPLE_DEF_LINK_ERR)"
    #else
    #pragma message "notdef(EXAMPLE_DEF_LINK_ERR)"
    #endif
    auto const var_dec_def = x3::lexeme["var "]
    > +x3::alnum
    > ":"
    #ifdef EXAMPLE_DEF_LINK_ERR
    >> type //<- this gets linker error.
    #else
    > type //<- This links.
    #endif
    > ";";

    BOOST_SPIRIT_DEFINE(
    var_dec
    )

    }}

    namespace client {

    const parser::var_dec_type& var_dec()
    {
    return parser::var_dec;
    }

    }

    #endif //LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP
  • 例子.hpp

    #ifndef LINKER_ERROR_EXAMPLE_EXAMPLE_HPP
    #define LINKER_ERROR_EXAMPLE_EXAMPLE_HPP

    #include <boost/spirit/home/x3.hpp>

    #include "ast.hpp"

    namespace client { namespace parser {

    namespace x3 = boost::spirit::x3;

    class var_dec_class {};

    typedef x3::rule<var_dec_class, ast::VariableDec> var_dec_type;

    BOOST_SPIRIT_DECLARE(var_dec_type)


    }}

    namespace client {

    const parser::var_dec_type& var_dec();

    }
    #endif //LINKER_ERROR_EXAMPLE_EXAMPLE_HPP
  • types_def.hpp

    #ifndef KYLE_TYPES_DEF_HPP
    #define KYLE_TYPES_DEF_HPP

    #include "types.hpp"


    namespace client { namespace parser {
    namespace x3 = boost::spirit::x3;


    typedef x3::rule<struct lambda_type_class, ast::LambdaType> lambda_type_type;


    const class_type_type class_type = "class_type";
    const lambda_type_type lambda_type = "lambda_type";
    const type_type type = "type";

    auto const identifier = +x3::alnum;

    auto const type_def =
    (lambda_type | class_type);

    auto const lambda_type_def =
    ("(" > -(type % ",") > ")" > "=>" > type)
    | (x3::repeat(1)[class_type] >> "=>" > type);


    auto const class_type_def =
    (identifier % "::") >> -("<" > type % "," > ">");


    BOOST_SPIRIT_DEFINE(
    lambda_type,
    class_type,
    type
    )


    }}

    namespace client {

    const parser::class_type_type& class_type()
    {
    return parser::class_type;
    }
    const parser::type_type& type()
    {
    return parser::type;
    }

    }

    #endif //KYLE_TYPES_DEF_HPP
  • 类型.hpp

    #ifndef KYLE_PARSER_TYPES_HPP
    #define KYLE_PARSER_TYPES_HPP

    #include <boost/spirit/home/x3.hpp>

    #include "ast.hpp"

    namespace client { namespace parser {
    namespace x3 = boost::spirit::x3;

    struct class_type_class;
    struct type_class;

    typedef x3::rule<class_type_class, ast::ClassType> class_type_type;
    typedef x3::rule<type_class, ast::Type> type_type;

    BOOST_SPIRIT_DECLARE(class_type_type,
    type_type)


    }}


    namespace client {

    const parser::class_type_type& class_type();
    const parser::type_type& type();

    }

    #endif

最佳答案

它抛出一个 expectation_failed 异常。

很明显,这是因为您缺少 ;

在清除了与旧的链接器错误解决方法相关的可怕错误之后,我只是将 example_def 表达式更改为:

auto const var_dec_def = x3::lexeme["var "] > +x3::alnum >> (":" > type) > ";";

现在,添加适当的错误处理:

int main()
{
client::ast::VariableDec attr;
std::string const input("var foo : foo<bar, baz<bahama>>;");

try {
std::cout << test(input, client::var_dec() , attr);
} catch(boost::spirit::x3::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "Expected: " << e.which() << " at '" << std::string(e.where(), input.end()) << "'\n";
return 255;
}
}

打印:

1

省略尾随 ; 打印:

Expected: ';' at ''

完整演示:error-handling分支机构

 CMakeLists.txt  |   6 +-
example.cpp | 9 +++
example_def.hpp | 33 +--------
main.cpp | 20 ++----
types.cpp | 203 ++++----------------------------------------------------
types_def.hpp | 20 ++----
6 files changed, 38 insertions(+), 253 deletions(-)
  • 例子.cpp

    #include "example_def.hpp"
    #include "config.hpp"

    namespace client { namespace parser {

    BOOST_SPIRIT_INSTANTIATE(var_dec_type, iterator_type, context_type)

    }}

    namespace client {

    const parser::var_dec_type& var_dec()
    {
    return parser::var_dec;
    }

    }
  • main.cpp

    #include <iostream>
    #include "example.hpp"

    template<typename Parser, typename Attribute>
    bool test(const std::string& str, Parser&& p, Attribute&& attr)
    {
    using iterator_type = std::string::const_iterator;
    iterator_type in = str.begin();
    iterator_type end = str.end();

    bool ret = boost::spirit::x3::phrase_parse(in, end, p, boost::spirit::x3::ascii::space, attr);
    ret &= (in == end);
    return ret;

    }

    int main()
    {
    client::ast::VariableDec attr;
    std::string const input("var foo : foo<bar, baz<bahama>>");

    try {
    std::cout << test(input, client::var_dec() , attr);
    } catch(boost::spirit::x3::expectation_failure<std::string::const_iterator> const& e) {
    std::cout << "Expected: " << e.which() << " at '" << std::string(e.where(), input.end()) << "'\n";
    return 255;
    }
    }
  • 类型.cpp

    #include "config.hpp"
    #include "types_def.hpp"

    namespace client {namespace parser {

    BOOST_SPIRIT_INSTANTIATE(type_type, iterator_type, context_type);

    BOOST_SPIRIT_INSTANTIATE(class_type_type, iterator_type, context_type);

    }}


    namespace client {

    const parser::class_type_type& class_type()
    {
    return parser::class_type;
    }
    const parser::type_type& type()
    {
    return parser::type;
    }

    }
  • ast.hpp

    //
    // Created by lukas on 11.11.16.
    //

    #ifndef LINKER_ERROR_EXAMPLE_AST_HPP_HPP
    #define LINKER_ERROR_EXAMPLE_AST_HPP_HPP

    #include <boost/fusion/adapted/struct.hpp>
    #include <boost/spirit/home/x3.hpp>
    #include <boost/spirit/home/x3/support/ast/variant.hpp>

    #include <vector>
    #include <string>

    namespace client { namespace ast {

    namespace x3 = boost::spirit::x3;

    struct LambdaType;
    struct ClassType;
    struct nil{};

    typedef x3::variant <
    nil,
    x3::forward_ast<LambdaType>,
    x3::forward_ast<ClassType>
    > Type;

    struct LambdaType {
    std::vector<Type> parameters_;
    Type return_type_;
    };

    struct ClassType {
    std::vector<std::string> name_;
    std::vector<Type> template_args_;
    };

    struct VariableDec {
    std::string _name;
    Type _type;
    };


    }}

    BOOST_FUSION_ADAPT_STRUCT(client::ast::LambdaType, parameters_, return_type_)
    BOOST_FUSION_ADAPT_STRUCT(client::ast::ClassType, name_, template_args_)
    BOOST_FUSION_ADAPT_STRUCT(client::ast::VariableDec, _name, _type)

    #endif //LINKER_ERROR_EXAMPLE_AST_HPP_HPP
  • 配置.hpp

    #ifndef LINKER_ERROR_EXAMPLE_CONFIG_HPP
    #define LINKER_ERROR_EXAMPLE_CONFIG_HPP

    #include <boost/spirit/home/x3.hpp>

    namespace client{
    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;

    }
    }

    #endif //LINKER_ERROR_EXAMPLE_CONFIG_HPP
  • example_def.hpp

    #ifndef LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP
    #define LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP

    #include "ast.hpp"
    #include "example.hpp"
    #include "types.hpp"

    namespace client { namespace parser {

    namespace { const auto& type = client::type(); }

    const var_dec_type var_dec = "var_dec";

    auto const var_dec_def = x3::lexeme["var "] > +x3::alnum >> (":" > type) > ";";

    BOOST_SPIRIT_DEFINE(var_dec)

    }}

    #endif //LINKER_ERROR_EXAMPLE_EXAMPLE_DEF_HPP
  • 例子.hpp

    #ifndef LINKER_ERROR_EXAMPLE_EXAMPLE_HPP
    #define LINKER_ERROR_EXAMPLE_EXAMPLE_HPP

    #include <boost/spirit/home/x3.hpp>

    #include "ast.hpp"

    namespace client { namespace parser {

    namespace x3 = boost::spirit::x3;

    class var_dec_class {};

    typedef x3::rule<var_dec_class, ast::VariableDec> var_dec_type;

    BOOST_SPIRIT_DECLARE(var_dec_type)


    }}

    namespace client {

    const parser::var_dec_type& var_dec();

    }
    #endif //LINKER_ERROR_EXAMPLE_EXAMPLE_HPP
  • types_def.hpp

    #ifndef KYLE_TYPES_DEF_HPP
    #define KYLE_TYPES_DEF_HPP

    #include "types.hpp"


    namespace client { namespace parser {
    namespace x3 = boost::spirit::x3;


    typedef x3::rule<struct lambda_type_class, ast::LambdaType> lambda_type_type;


    const class_type_type class_type = "class_type";
    const lambda_type_type lambda_type = "lambda_type";
    const type_type type = "type";

    auto const identifier = +x3::alnum;

    auto const type_def =
    (lambda_type | class_type);

    auto const lambda_type_def =
    ("(" > -(type % ",") > ")" > "=>" > type)
    | x3::repeat(1)[class_type] >> "=>" > type;


    auto const class_type_def =
    (identifier % "::") >> -("<" > type % "," > ">");


    BOOST_SPIRIT_DEFINE(
    lambda_type,
    class_type,
    type
    )


    }}


    #endif //KYLE_TYPES_DEF_HPP
  • 类型.hpp

    #ifndef KYLE_PARSER_TYPES_HPP
    #define KYLE_PARSER_TYPES_HPP

    #include <boost/spirit/home/x3.hpp>

    #include "ast.hpp"

    namespace client { namespace parser {
    namespace x3 = boost::spirit::x3;

    struct class_type_class;
    struct type_class;

    typedef x3::rule<class_type_class, ast::ClassType> class_type_type;
    typedef x3::rule<type_class, ast::Type> type_type;

    BOOST_SPIRIT_DECLARE(class_type_type,
    type_type)


    }}


    namespace client {

    const parser::class_type_type& class_type();
    const parser::type_type& type();

    }

    #endif

关于c++ - Boost spirit x3 解析器在解析时抛出 std::logic_error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40667770/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com