问候。
我一直很有兴趣在解析语法和生成AST时如何强制boost :: spirit生成不同类的节点。比方说,我希望有不同的节点,如VariableNode(其变量名称为其成员),ValueNode(其值为其成员)等。
在处理树木行走者时会非常有用。在这种情况下,我们将编写一个基本抽象类,用于遍历所有不同的节点(应用“访问者”模式)并在处理语义检查阶段,代码生成阶段等时扩展它。
boost :: spirit允许我们参数化用于树的工厂,但我一直无法找到调整其行为的正确方法。
任何想法,代码?提前谢谢。
答案 0 :(得分:3)
我不确定我理解你的问题,你的意思是这样吗? :
typedef boost::variant<VariableNode, ValueNode> AbstractNode;
template <typename Iterator>
struct NodeGrammar: public boost::spirit::qi::grammar<Iterator, AbstractNode(), boost::spirit::ascii::space_type>
{
NodeGrammar: NodeGrammar::base_type(start)
{
start %= variableNode | valueNode >> eps;
variableNode %= /*something*/;
valueNode %= /*something*/;
}
//start
boost::spirit::qi::rule<Iterator, AbstractNode(), boost::spirit::ascii::space_type> start;
boost::spirit::qi::rule<Iterator, VariableNode(), boost::spirit::ascii::space_type> variableNode;
boost::spirit::qi::rule<Iterator, ValueNode(), boost::spirit::ascii::space_type> valueNode;
};
然后,您可以将boost :: apply_visitor(请参阅boost :: variant文档)与访问者类一起使用,以执行您想要的行为。
答案 1 :(得分:1)
要回答你的评论(你可能想为此开始一个新的问题):标识符应该存储在qi :: symbols-derived类中,关键字将存在于你的其他qi ::规则中。
至于2)这将是这样的(未经测试):
class ScriptNodes
{
//this will enable fusion_adapt_struct to access your private members
template < typename, int>
friend struct boost::fusion::extension::struct_member;
private:
typdef std::vector<boost::shared_ptr<UserFuncNode> > Nodes
Nodes nodes;
};
//when using fusion_adapt_struct, try to typedef any type that contain a ,
//since it will confuse the macro (ex std::pair<int, int>)
BOOST_FUSION_ADAPT_STRUCT(
ScriptNode,
(ScriptNodes::Nodes, nodes)
)
...
using boost::spirit::qi::grammar;
using boost::spirit::ascii::space_type;
template <typename Iterator>
struct NodeGrammar: public grammar<Iterator, ScriptNodes(), space_type>
{
NodeGrammar: NodeGrammar::base_type(start)
{
using namespace boost::spirit::arg_names;
using boost::spirit::arg_names::_1;
//the %= should automatically store the user_func nodes in start
//for more complex rules you might need to do the push_back manually
//using phoenix::push_back
start %= *user_func >> eps;
//this should parse a double and create a new UserFuncNode with the
//parsed argument and the result will be assigned in the shared_ptr
//variable stored in a user_func
user_func = double_[_val = new UserFuncNode(_1)];
}
using boost::spirit::qi::rule;
using boost::shared_ptr;
//start
rule<Iterator, ScriptNodes(), space_type> start;
rule<Iterator, shared_ptr<UserFuncNode>(), space_type> user_func;
};
如果你需要我可能会花费更多,但是如果你有特定的问题你可能会开始一个新的问题,所以其他人也可以提供帮助,因为我只是boost :: spirit的初学者用户,他们可能有更好的答案。
干杯