Skip to content
Snippets Groups Projects
SetupData.hh 6.68 KiB
Newer Older
Matthias Steinke's avatar
Matthias Steinke committed
#ifndef SETUPDATA_HH
#define SETUPDATA_HH

#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_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>


namespace setupData
{
  namespace fusion = boost::fusion;
  namespace phoenix = boost::phoenix;
  namespace qi = boost::spirit::qi;
  namespace ascii = boost::spirit::ascii;
  
  ///////////////////////////////////////////////////////////////////////////
  //  Our mini DECAY tree representation
  ///////////////////////////////////////////////////////////////////////////

  struct decay_tree;
  
  typedef
  boost::variant<
    boost::recursive_wrapper<decay_tree>
    , std::string
    >
  decay_node;
  
  struct decay_tree
  {
    std::string name;                        // mother particle name
    std::vector<decay_node> children;        // children
    std::vector<std::string> addParticle;
    std::vector<std::string> cloneParticle;
    std::vector<std::string> modParticle;
    std::vector<std::string> beamInput;
    std::vector<std::string> mcInput;
    std::vector<std::string> defineTuple;
    std::vector<std::string> fitVars;
    std::vector<std::string> initialProps;
  };
}

// We need to tell fusion about our setup struct
// to make it a first-class fusion citizen

BOOST_FUSION_ADAPT_STRUCT(
    setupData::decay_tree,
    (std::string, name)
    (std::vector<setupData::decay_node>, children)
    (std::vector<std::string>, addParticle)
    (std::vector<std::string>, cloneParticle)
    (std::vector<std::string>, modParticle)
    (std::vector<std::string>, beamInput)
    (std::vector<std::string>, mcInput)
    (std::vector<std::string>, defineTuple)
    (std::vector<std::string>, fitVars)
    (std::vector<std::string>, initialProps)
)

namespace setupData
{
    ///////////////////////////////////////////////////////////////////////////
    //  Print out the mini decay tree
    ///////////////////////////////////////////////////////////////////////////
    int const tabsize = 4;

    void tab(int indent)
    {
        for (int i = 0; i < indent; ++i)
            std::cout << ' ';
    }

    struct decay_tree_printer
    {
        decay_tree_printer(int indent = 0)
          : indent(indent)
        {
        }

        void operator()(decay_tree const& decay) const;

        int indent;
    };

    struct decay_node_printer : boost::static_visitor<>
    {
        decay_node_printer(int indent = 0)
          : indent(indent)
        {
        }

        void operator()(decay_tree const& decay) const
        {
            decay_tree_printer(indent+tabsize)(decay);
        }

        void operator()(std::string const& text) const
        {
            tab(indent+tabsize);
            std::cout << "text: \"" << text << '"' << std::endl;
        }

        int indent;
    };

    void decay_tree_printer::operator()(decay_tree const& decay) const
    {
        tab(indent);
        std::cout << "tag: " << decay.name << std::endl;
        tab(indent);
        std::cout << '{' << std::endl;

        BOOST_FOREACH(decay_node const& node, decay.children)
        {
            boost::apply_visitor(decay_node_printer(indent), node);
        }

        tab(indent);

        std::vector<std::string>::const_iterator iter;
        
        iter = decay.addParticle.begin();
        while (iter != decay.addParticle.end()) {
          std::cout << "new particle: " << *iter << std::endl;
          ++iter;
        }

        iter = decay.cloneParticle.begin();
        while (iter != decay.cloneParticle.end()) {
          std::cout << "cloned particle: " << *iter << std::endl;
          ++iter;
        }

        iter = decay.modParticle.begin();
        while (iter != decay.modParticle.end()) {
          std::cout << "modified particle: " << *iter << std::endl;
          ++iter;
        }

        std::cout << '}' << std::endl;
    }

    ///////////////////////////////////////////////////////////////////////////
    //  Our mini DECAY grammar definition
    ///////////////////////////////////////////////////////////////////////////
    //[tutorial_decay1_grammar
    template <typename Iterator>
    struct setup_file_grammar : qi::grammar<Iterator, decay_tree(), ascii::space_type>
    {
      setup_file_grammar() : setup_file_grammar::base_type(decay)
        {
          using qi::lit;
          using qi::lexeme;
          using ascii::char_;
          using ascii::string;
          using namespace qi::labels;
          
          using phoenix::at_c;
          using phoenix::push_back;
          using boost::phoenix::ref;

          restOfLine = lexeme[*(char_ -'\n') [_val += _1]];
          comment = (char_('#') >> lexeme[*(char_ -'\n')]);

          particleName = lexeme[+(char_('!','z') -',') [_val += _1]];
          decNode = (decay | particleName);
          goesTo = char_('-') >> char_('>');
          
          decay = +( comment ||
                     "addParticle"        >> restOfLine[push_back(at_c<2>(_val), _1)] || 
                     "cloneParticle"      >> restOfLine[push_back(at_c<3>(_val), _1)] || 
                     "modParticle"        >> restOfLine[push_back(at_c<4>(_val), _1)] || 
                     "beamInput"          >> restOfLine[push_back(at_c<5>(_val), _1)] || 
                     "mcInput"            >> restOfLine[push_back(at_c<6>(_val), _1)] || 
                     "defineTuple"        >> restOfLine[push_back(at_c<7>(_val), _1)] || 
                     "fitVariables"       >> restOfLine[push_back(at_c<8>(_val), _1)] || 
                     "initialProperties"  >> restOfLine[push_back(at_c<9>(_val), _1)] || 
                    ( char_('{')
                      >> (decay[push_back(at_c<1>(_val), _1)] || particleName[at_c<0>(_val) = _1])
                      >> goesTo
                      >> decNode   [push_back(at_c<1>(_val), _1)]
                      >> ','
                      >> decNode   [push_back(at_c<1>(_val), _1)]
                      >> char_('}') )
                    );
          
        }

        
        qi::rule<Iterator, decay_tree(), ascii::space_type> decay;
        qi::rule<Iterator, decay_node(), ascii::space_type> decNode;
        qi::rule<Iterator, std::string(), ascii::space_type> goesTo;
        qi::rule<Iterator, std::string(), ascii::space_type> comment;
        qi::rule<Iterator, std::string(), ascii::space_type> restOfLine;
        qi::rule<Iterator, std::string(), ascii::space_type> particleName;
    };

}

#endif