Ok Ich habe nun den Funktionsparser neu geschrieben mittels boost::spirit::qi
Kritik erwünscht.
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace QiSubroutines {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
typedef std::vector <std::pair <std::string, std::string> > paramContainerType;
struct SubroutineBase {
std::string name;
paramContainerType parameters;
};
}
BOOST_FUSION_ADAPT_STRUCT(
QiSubroutines::SubroutineBase,
(std::string, name)
(QiSubroutines::paramContainerType, parameters)
)
namespace QiSubroutines {
template <typename iterator_type>
struct subroutine_parser : qi::grammar <iterator_type, SubroutineBase(), ascii::space_type>
{
subroutine_parser(): subroutine_parser::base_type(start, "subroutine")
{
using qi::lexeme;
using ascii::char_;
using qi::alpha;
using qi::space;
using qi::on_error;
using qi::fail;
using phoenix::at_c;
using phoenix::push_back;
using namespace qi::labels;
using phoenix::construct;
using phoenix::val;
valid_text %= lexeme[+alpha];
argpair =
lexeme[+alpha [at_c<0>(_val) += _1]]
> lexeme[+alpha [at_c<1>(_val) += _1]]
>> -char_(',')
;
start =
valid_text [at_c<0>(_val) = _1]
> char_('(')
>> *argpair [phoenix::push_back(at_c<1>(_val), _1)]
> char_(')')
> char_(';')
;
start.name("qi_subroutine");
argpair.name("argpair");
valid_text.name("valid_text");
on_error<fail>
(
start ,
std::cout << val("Error in subroutine parser - expecting: ")
<< _4
<< val( " here: \"")
<< construct<std::string> (_3, _2)
<< val("\"\n")
);
}
qi::rule <iterator_type, std::string(), ascii::space_type> valid_text;
qi::rule <iterator_type, std::pair<std::string, std::string> (), ascii::space_type> argpair;
qi::rule <iterator_type, SubroutineBase(), ascii::space_type> start;
};
}
Main
int main()
{
std::string str = "Name(int a, double b);";
using QiSubroutines::SubroutineBase;
using QiSubroutines::subroutine_parser;
using boost::spirit::ascii::space;
using boost::spirit::qi::phrase_parse;
SubroutineBase base;
bool ret = phrase_parse<std::string::const_iterator>
(str.begin(),
str.end(),
subroutine_parser<std::string::const_iterator>(),
space,
base);
if (!ret)
std::cout << "dadümm\n";
else {
std::cout << "Name: " << base.name << "\n";
for (auto i = base.parameters.begin(); i != base.parameters.end(); ++i) {
std::cout << "parm pair: " << i->first << "-" << i->second << "\n";
}
}
return 0;
}
EDIT: Die Lösung macht micht schon deutlich glücklicher.
EDIT: boost::spirit::qi macht so viel fun, ich habe gleich mit den Schleifen weitergemacht