Boost logo

Boost Users :

Subject: Re: [Boost-users] [Spirit.Qi] How do I get Rule Name/Id through Semantic Action / Phoenix variable
From: HT4N - (ht4n_at_[hidden])
Date: 2009-11-22 22:37:13


 
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_at_[hidden]
>> To: boost-users_at_[hidden]
>> 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_at_[hidden]
>>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>>
>> _______________________________________________
>> Boost-users mailing list
>> Boost-users_at_[hidden]
>> 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:WLMTAGL:ON:WL:en-US:WWL_WIN_evergreen:112009v2
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> 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:WLMTAGL:ON:WL:en-US:WWL_WIN_evergreen:112009v2


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net