我已经得到了一个人类定义的语法定义:
"my car is moving [speed] while I feel [feeling]"
我将其翻译为std::vector<std::string>
:
"my car is moving", "[speed]", "while I feel", "[feeling]"
现在我建立了一个解析速度的规则:
using boost::spirit::ascii::string;
namespace phoenix = boost::phoenix;
namespace spirit = boost::spirit;
namespace qi = boost::spirit::qi;
struct quantity {
double factor;
std::string unit;
bool operator==(const quantity& other) { return other.factor == factor && other.unit == unit; }
};
// see http://stackoverflow.com/questions/18602818/boost-spirit-qi-custom-syntesized-attribute-set-a-specific-member-of-a-struct-a
auto quantity_factor_field = phoenix::bind(&quantity::factor, qi::_val);
auto quantity_unit_field = phoenix::bind(&quantity::unit, qi::_val);
auto expression_unit_velocity_kmh = "km" >> -(string("/")) >> "h";
auto expression_unit_distance_m = string("m");
qi::rule<std::string::const_iterator, quantity()> numeric_value_expression;
numeric_value_expression = qi::double_[quantity_factor_field = qi::_1] >>
(
expression_unit_velocity_kmh[quantity_unit_field = "m/s", quantity_factor_field /= 3.6] |
expression_unit_distance_m[quantity_unit_field = "m"]
);
现在numeric_value_expression
工作正常。我的问题现在是这些规则的动态组合。我不能使用Nabialek技巧,因为选择的符号取决于我的令牌数组。结合规则的最佳方法是什么?我只是尝试过类似的东西:
auto push_back_result_to_quantity_field = phoenix::push_back(phoenix::bind(&parsing_result::quantities, qi::_val), qi::_1);
for (const std::string &token : tokens) {
if (token == "[speed]")
final_rule = final_rule.copy() >> numeric_value_expression[push_back_result_to_quantity_field];
else if (token = ...)
}
这有效,但只有一个令牌会被保护,之前的所有令牌都会丢失。 (因此在示例中仅存储最后的[feeling]
。