Reputation: 89
I get already a human-defined grammar definition in the style of:
"my car is moving [speed] while I feel [feeling]"
I translated this to a std::vector<std::string>
:
"my car is moving", "[speed]", "while I feel", "[feeling]"
Now I built up a rule for parsing speed:
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"]
);
Now the numeric_value_expression
works fine. My problem is now the dynamic combination of those rules. I can't use the Nabialek trick because the symbol choosing depends on my token array. What is the best approach to combine rules? I simply tried something like:
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 = ...)
}
This worked but only one token will be safed, all previous are lost. (So in the example only the last [feeling]
will be stored.
Upvotes: 1
Views: 65