Boost logo

Boost Users :

Subject: Re: [Boost-users] [Spirit.Qi] How do I get Rule Name/Id through Semantic Action / Phoenix variable
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2009-11-22 10:02:21


> 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>
> {
> <value_str>foo</value_str>
> <value_int>1</value_int>
> }
> <nonterminal>
> {
> <value_str>bar</value_str>
> <value_int>2</value_int>
> }
> }
>
> 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<ptnode_var> 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<client::ptnode_var>, children)
> )
> //]
> namespace client
> {
> template <typename Iterator>
> struct ExpressionGrammar : qi::grammar<Iterator, ptnode(),
> 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<Iterator, ptnode(), ascii::space_type> Option;
> qi::rule<Iterator, ptnode(), ascii::space_type> Expression;
> qi::rule<Iterator, string(), ascii::space_type> ParameterName;
> qi::rule<Iterator, int(), ascii::space_type> 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("<value_str>%s</value_str>\n", val.c_str());
> }
>
> void operator()(const int& val) const
> {
> tab(indent+tabsize);
> printf_s("<value_int>%d</value_int>\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 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