我想在语义操作中更改局部变量值,如下所示:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;
using boost::phoenix::bind;
void dummy(const std::vector<char>& v, int& var)
{
var = 7;
}
template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, std::string(), ascii::space_type>
{
public:
x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
{
using namespace qi;
int local_var = 0;
start_rule = (+(char_ - ";"))[bind(dummy, _1, ref(local_var))];
//repeat(ref(local_var))[some_rule];
}
private:
qi::rule<Iterator, std::string(), ascii::space_type> start_rule;
};
int main()
{
typedef std::string::const_iterator iter;
std::string storage("string;aaa");
iter it_begin(storage.begin());
iter it_end(storage.end());
std::string read_data;
using boost::spirit::ascii::space;
x_grammar<iter> g;
try {
bool r = qi::phrase_parse(it_begin, it_end, g, space, read_data);
std::cout << "Pass!\n";
} catch (const qi::expectation_failure<iter>& x) {
std::cout << "Error!\n";
}
}
我在使用带有 boost 1.55 的 GCC 4.6.1 时遇到一些恼人的编译错误。
最佳答案
我不禁要注意,如果编译器错误让您烦恼,那么也许您应该编写有效的代码:/
指导性的帽子......
虽然这当然是一个轻率的评论,但它也具有一定的启发性。
我已经两次告诉你,在你的语法中使用构造函数局部变量的整个想法从根本上被打破了:
你想要的是
- 继承属性
- qi::本地人
- maayyyyybe, maaaayyybe语法成员变量;需要注意的是,它们会使您的规则不可重入。
真正进入你头脑的重要事情是
Boost Spirit generates parser from expression templates. Expression templates are 90% static information (type only), and get "compiled" (
.compile()
) into "invokable" (.parse()
) form.Most importantly, while you can write control flow in your semantic actions, none of this actually executed at the definition site. It's "compiled" into a lazy actor that can later be invoked.
The generated parse will conditionally invoke the lazy actor when the corresponding parse expression matches
建设性的帽子...
看起来您只想使用函数转换属性。
以下是您可以执行的操作:
将转换作为语义操作的一部分,将结果放入常规属性(为解析器组合维护“功能”语义):
qi::rule<Iterator, exposed(), Skipper> myrule; myrule = int_ [ _val = phx::bind(custom_xform, _1) ];
custom_xform
是任何老派的可调用对象(包括多态可调用对象):exposed custom_xform(int i) { return make_new_exposed(i); } // or struct custom_xfrom_t { template <typename> struct result { typedef exposed type; }; template <typename Int> exposed operator()(Int i) const { return make_new_exposed(i); } }; static const custom_xform_t custom_xform;
你可以添加一些语法糖[1]
qi::rule<Iterator, exposed(), Skipper> myrule; myrule = int_ [ _val = custom_xform(_1) ];
这需要将
custom_xform
定义为惰性 actor:phx::function<custom_xform_t> custom_xform; // `custom_xform_t` again the (polymorphic) functor
You may note this wouldn't work for a regular function. You could wrap it in a calleable object, or use the
BOOST_PHOENIX_ADAPT_FUNCTION
macro to do just that for you如果您想要更频繁地应用一些更复杂的转换,请考虑使用 Spirit Customization Points:
如果您为属性选择特定类型(例如
Ast::Multiplicity
或Ast::VelocityRanking
,而不是int
或double
[1] 使用 BOOST_SPIRIT_USE_PHOENIX_V3
关于c++ - 在语义 Action 中 boost spirit 改变变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23788538/