Attribute propagation vs. Semantic actions

Joel de Guzman <[email protected]> Tue, 16 Mar 2010 21:11:44 +0800
Newsgroups gmane.comp.parsers.spirit.devel
Message-ID <[email protected]>
Hi Y'all,

CC'ing Hartmut and John Wilkinson.

I've been looking into attribute propagation vs. semantic actions
lately. It has come to my attention that attribute propagation is
not as efficient as we thought it would be (perhaps due to some recent
changes and strategies we have incorporated). Here's a test case
that does the same thing with attribute propagation and with semantic
actions. Just define ATTR_PROPAGATE to choose the former, or undefine
for the latter. Here's the printout with attribute propagation:

     default construct
     construct from char
     assign
     copy construct
     default construct
     construct from char
     assign
     copy construct
     copy construct
     default construct
     assign
     construct from char
     assign
     copy construct
     copy construct
     copy construct
     default construct
     assign
     construct from char
     assign
     copy construct
     copy construct
     copy construct
     copy construct
     default construct
     assign
     construct from char
     assign
     copy construct
     copy construct
     copy construct
     copy construct
     copy construct
     default construct
     assign

Now with actions:

     construct from char
     copy construct
     construct from char
     copy construct
     copy construct
     construct from char
     copy construct
     copy construct
     copy construct
     construct from char
     copy construct
     copy construct
     copy construct
     copy construct
     construct from char
     copy construct
     copy construct
     copy construct
     copy construct
     copy construct

Obviously, the one with semantic actions win. Notice though that
on both cases, there's way too much copying. I suspect unwanted
copying of the vector. Man, this is unacceptable. We have to fix this!

Regards,
-- 
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net
http://www.facebook.com/djowel

Meet me at BoostCon
http://www.boostcon.com/home
http://www.facebook.com/boostcon

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev

_______________________________________________
Spirit-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-devel
attr_vs_actions.cpp (text/x-c++src, 2.2 KB)
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

#include <iostream>
#include <string>
#include <complex>

using boost::spirit::qi::grammar;
using boost::spirit::qi::rule;
using boost::spirit::qi::char_;
using boost::spirit::qi::parse;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;
using boost::phoenix::push_back;

//~ #define ATTR_PROPAGATE

struct test_attr
{
    test_attr()
    {
        std::cout << "default construct" << std::endl;
    }

    test_attr(char)
    {
        std::cout << "construct from char" << std::endl;
    }

    test_attr(test_attr const&)
    {
        std::cout << "copy construct" << std::endl;
    }

    test_attr& operator=(test_attr const&)
    {
        std::cout << "assign" << std::endl;
        return *this;
    }
};

template <typename Iterator>
struct test_parser : grammar<Iterator, std::vector<test_attr>() >
{
    test_parser() : test_parser::base_type(start)
    {
#ifdef ATTR_PROPAGATE
        start = char_ >> *(',' >> char_);
#else
        start = char_[push_back(_val, _1)] >> *(',' >> char_[push_back(_val, _1)]);
#endif
    }

    rule<Iterator, std::vector<test_attr>()> start;
};

int main()
{
    typedef std::string::const_iterator iterator_type;
    typedef test_parser<iterator_type> test_parser;

    test_parser g;
    std::string str = "a,b,c,d,e";

    std::vector<test_attr> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = parse(iter, end, g, result);

    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "\n-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}