[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
<nonterminal>
{
<nonterminal>
{

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 <nonterminal> { <nonterminal> {
foo 1 } <nonterminal> {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 :
<Option> <Expression> <ParameterName>foo</ParameterName> <ParameterValue>1</ParameterValue> </Expression> <Expression> <ParameterName>bar</ParameterName> <ParameterValue>2</ParameterValue> </Expression> </Option>
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> > ptnode_var;
/////////////////////////////////////////////////////////////////////// //// // Our AST
/////////////////////////////////////////////////////////////////////// //// struct ptnode { ptnode() : data(nil()) { } template<typename T> 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::vectorclient::ptnode_var, children) ) //] namespace client { template <typename Iterator> struct ExpressionGrammar : qi::grammar { 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("<nonterminal>\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

"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...

I am sorry my previous post missing my actual reply. Instead of using rule name, I actually wants to store rule id for efficiency reason. So, my idea is, after I push _1 to the children node of Option ptnode, I also want to set the rule id to the ptnode.data of Option ptnode. I was thinking along adding 2nd semantic action by calling at_c<0>(_val) = OptionId. This does not seem to work as it seems a second copy of _val is created and replace the first copy created when the push_back() is called. Hence between the first semantic call and 2nd call it works on 2 different ptnode object. Option = *(Expression) [ push_back(at_c<1>(_val), _1), at_c<0>(_val) = OptionId ] Unfortunately I am very new to fusion/phoenix so the concept is still very vague for me. I guess I can achieve the above intention if I know how to access the same object from two different semantic action within the same [...]. That way I can set different fields at different invocation of semantic action. At the end of the story What I am trying to achieve is that for each rule parsed, I want to store into a node {id, children} of type ptnode where children is a vector of boost variant of type string, int, ptnode. Appreciate your help. Thanks HT
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)];
----------------------------------------
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... _______________________________________________ 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...
participants (2)
-
Hartmut Kaiser
-
HT4N -