
"i bing u bing" ----------------------------------------
From: hartmut.kaiser@gmail.com To: boost-users@lists.boost.org Date: Sun, 22 Nov 2009 09:02:21 -0600 Subject: Re: [Boost-users] [Spirit.Qi] How do I get Rule Name/Id through Semantic Action / Phoenix variable
I want to create a generic Parse Tree from a simple expression grammar (see below code snippet). Using the Mini_XML as the reference, I was able to create a Parse Tree close to what I want.
If I run my simple program and parse an expressions "[foo=1 bar=2]", for example, it will printout the following Parse Tree:
[foo=1 bar=2] ------------------------- Parsing succeeded
{
{ foo 1 }
{ bar 2 } }
The next thing I want to achieve is to have the Parse Tree looks very similar to the one produced in Spirit.Classic. In Spirit.Classic for each node it has RuleId for which we associate it with a RuleName so that when we are iterating the node of the Parse Tree we can printout the RuleName. In other words, instead I want the above Parse Tree to look like the following :
foo 1
bar 2
In other words, what I need to know is how I can get the Rule Name/Id through semantic actions/phoenix variable. Any pointer is appreciated.
You should be able to bind the rule's member function name() and call it from inside a semantic action:
rule<...> r; r.name("my_rule");
r = p[... = bind(&rule<...>::name, r)];
Regards Hartmut
------------------- Meet me at BoostCon http://boostcon.com
Thanks again.
HT
Code Snippet: namespace client { struct ptnode; typedef boost::variant< nil, unsigned int, string, boost::recursive_wrapper
ptnode_var;
/////////////////////////////////////////////////////////////////////// //// // Our AST
/////////////////////////////////////////////////////////////////////// //// struct ptnode { ptnode() : data(nil()) { } template ptnode(const T& data) : data(data) { } ptnode_var data; vector children; }; } // We need to tell fusion about our mini_xml struct // to make it a first-class fusion citizen //[tutorial_xml1_adapt_structures BOOST_FUSION_ADAPT_STRUCT( client::ptnode, (client::ptnode_var, data) (std::vector, children) ) //] namespace client { template struct ExpressionGrammar : qi::grammar>> ascii::space_type> { ExpressionGrammar() : ExpressionGrammar::base_type(Option) { using qi::_val; using qi::_1; using qi::char_; using qi::alnum; using qi::alpha; using qi::lexeme; using qi::raw; using qi::uint_; using phoenix::at_c; using phoenix::push_back; Option = char_('[')
*Expression [push_back(at_c<1>(_val), _1)] char_(']'); Expression = ParameterName [push_back(at_c<1>(_val), _1)] (char_('=')>> ParameterValue [push_back(at_c<1>(_val), _1)]); ParameterName = lexeme[+(alnum) [_val += _1]]; ParameterValue = uint_ [_val = _1]; Option.name("Option"); Expression.name("Expression"); ParameterName.name("ParameterName"); ParameterValue.name("ParameterValue"); } qi::rule Option; qi::rule Expression; qi::rule ParameterName; qi::rule ParameterValue; };
/////////////////////////////////////////////////////////////////////// //// // Print out the mini xml tree
/////////////////////////////////////////////////////////////////////// //// int const tabsize = 4; void tab(int indent) { for (int i = 0; i < indent; ++i) { printf_s(" "); } }
struct ptnode_printer { ptnode_printer(int indent = 0) : indent(indent) { } void operator()(ptnode const& node) const; int indent; };
struct ptnode_var_printer : boost::static_visitor<> { ptnode_var_printer(int indent = 0) : indent(indent) { }
void operator()(const ptnode& var) const { ptnode_printer(indent+tabsize)(var); }
void operator()(const nil&) const { // Print node type ... tab(indent); printf_s("\n"); }
void operator()(const string& val) const { tab(indent+tabsize); printf_s("%s\n", val.c_str()); }
void operator()(const int& val) const { tab(indent+tabsize); printf_s("%d\n", val); }
int indent; };
void ptnode_printer::operator()(const ptnode& node) const { boost::apply_visitor(ptnode_var_printer(indent), node.data); tab(indent); printf_s("{\n"); BOOST_FOREACH(const ptnode_var& child, node.children) { boost::apply_visitor(ptnode_var_printer(indent), child); } tab(indent); printf_s("}\n"); } }
_________________________________________________________________ Windows 7: I wanted simpler, now it's simpler. I'm a rock star. http://www.microsoft.com/Windows/windows- 7/default.aspx?h=myidea?ocid=PID24727::T:WLMTAGL:ON:WL:en- US:WWL_WIN_myidea:112009 _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Windows 7: It works the way you want. Learn more. http://www.microsoft.com/Windows/windows-7/default.aspx?ocid=PID24727::T:WLM...