在其他线程中,我已经阅读了如何在语义操作中向符号表添加符号,但我不知道如何删除它。
我的问题背后的想法是,我想允许在解析的文本中重命名关键字。因此,给出了几个带值的关键字,但用户可以重新分配它们:
reassign(keyword)(mykeyword)
我有一个带语义动作的规则
using namespace boost::spirit::qi;
...
qi::symbols<char, TYPE> keywords;
...
key_replace = ( lit("reassign") >> lit("(") >> keywords >> lit(")") >>
lit("(") >> lexeme [ raw [ ( alpha >> *( alnum | '_' ) ) ] ] >> lit (")") )
[ boost::phoenix::bind(keywords.remove, _1) ]; // TODO: replace not remove
问题是,我没有获得对符号本身的引用,而是引用了存储的值。因此调用remove不起作用。
如何在解析过程中获得对已解析符号的引用?
在解析过程中保留值时是否有更简单的方法来交换符号?
答案 0 :(得分:3)
天真的'凤凰'方式将是
rule_assign = key >> value
[ phx::bind(keywords.add, _1, _2) ];
rule_remove = key
[ phx::bind(keywords.remove, _1) ];
// and voila: (BROKEN)
rule_replace = key >> value
[ phx::bind(keywords.remove, _1),
phx::bind(keywords.add, _1, _2)
];
后者不起作用,我相信由于第一个绑定返回一个重载operator,
本身的对象,它优先于phoenix
的{{1}}。
我建议你写一个小帮手来解决这个问题:
operator,
这透明地分配或重新分配struct assign_symbol_f
{
assign_symbol_f(Symbols& sym) : sym(sym) {}
typedef bool result_type;
template<typename Key, typename Value>
bool operator()(Key const& key, Value const& value) const
{
bool replaced = (nullptr != sym.find(key));
sym.remove(key);
sym.add(key, value);
return replaced;
}
private:
Symbols& sym;
};
树中的项目。使用方法如下:
symbols
现在,你可以拆分并更具体:
rule_replace_or_add = key >> value
[ phx::bind(assign_symbol_f(keywords), qi::_1, qi::_2) ];
作为奖励,您可以通过为您的仿函数创建一个懒惰的演员来获得一些语法糖:
assign_symbol_f assign_sym(keywords);
rule_assign = key >> value
[ qi::_pass = !phx::bind(assign_sym, _1, _2) ];
rule_replace = key >> value
[ qi::_pass = phx::bind(assign_sym, _1, _2) ];
看吧!不再phx::function<assign_symbol_f> assign_sym;
// use it like
rule_assign = key >> value
[ qi::_pass = assign_sym(_1, _2) ];
rule_replace = key >> value
[ qi::_pass = assign_sym(_1, _2) ];
。
完成一个基本的测试套件:)
phx::bind