首页 > 解决方案 > boost::spirit 两次使用相同的符号

问题描述

我有一个类似的语法:

 template <class ITER>
struct MessageParser
    : public boost::spirit::qi::grammar<ITER, Message(), boost::spirit::ascii::space_type>
{
    MessageParser()
        : MessageParser::base_type(start_)
    {
        string_ = +(char_("a-zA-Z_") >> *char_("a-zA-Z_0-9"));
        quoted_string_ = lexeme['"' >> +(char_ - '"') >> '"'];
        signal_ %= lit("SG_")  // type is Signal
            >> string_ >> ':'; // Signal name
        message_ %= lit("BO_") // type is Message
            >> int_
            >> string_ >> ':'
            >> +signal_; // std::map<std::string, Signal> (here is my problem)
        start_ %= message_;
    }
    boost::spirit::qi::rule<ITER, Message(), boost::spirit::ascii::space_type> start_;
    boost::spirit::qi::rule<ITER, Message(), boost::spirit::ascii::space_type> message_;
    boost::spirit::qi::rule<ITER, Signal(), boost::spirit::ascii::space_type> signal_;
    boost::spirit::qi::rule<ITER, std::string()> string_;
    boost::spirit::qi::rule<ITER, std::string(), boost::spirit::ascii::space_type> quoted_string_;
};

问题是,我需要Signal创建Signal对象的名称(因为它有一个name属性),但我还想将使用规则解析的信号映射signal_到消息std::map<std::string, Signal>映射中的信号名称,但我不知道如何接收信号的名称,或者如何创建所需的信号对,boost::spirit以便将信号对插入到地图中。我想我必须以某种方式复制包含信号名称的字符串。

我怎样才能做到这一点?

标签: c++boostboost-spirit

解决方案


我解决了它attr_cast

namespace boost
{
    namespace spirit
    {
        namespace traits
        {
            template <>
            struct transform_attribute<std::pair<std::string, Signal>, Signal, boost::spirit::qi::domain>
            {
                using type = Signal&;
                using pair_t = std::pair<std::string, Signal>;
                static Signal& pre(pair_t& pair)
                {
                    return pair.second;
                }
                static void post(pair_t& pair, const Signal& sig)
                {
                    pair.first = sig.name;
                    pair.second = sig;
                }
                static void fail(pair_t& pair)
                {
                }
            };
        }
    }
}

接着:

message_ %= lit("BO_")
    >> int_
    >> string_ >> ':'
    >> int_
    >> string_
    >> +attr_cast(signal_);

我希望我使用的一切都是正确的(不保证)。


推荐阅读