我的语法与此相似:
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 signal_
到消息std::map<std::string, Signal>
中的信号名称映射,但是我不知道如何接收信号名称,或者如何为boost::spirit
创建所需的信号对,所以可以将其插入地图。
我想我必须以某种方式复制包含信号名称的字符串。
我该怎么做?
答案 0 :(得分:0)
我用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_);
我希望我使用了所有正确的信息(不保证)。