c++ - Boost Spirit Parser with a vector of three strings compiling into a struct, adapt not working -
i´m student , need write parser in c++ boost-library.
therefore write grammer in qi because need parse struct. far, good.
i give example-code. think easier writing whole program down.
description: first take txt-file , read it, parser goes on it, says "parsing ok!" , parse struct. our output struct in console.
that works fine, code examples. here can see grammar in boost spirit qi:
subject %= lexeme[lit("fach: ") >> +(char_("a-za-z")) >> lit("\n")]; //works! dozent %= lexeme[lit("dozent: ") >> +(char_("a-za-z")) >> lit("\n")]; date %= lexeme[lit("datum: ") >> digit >> digit >> lit("-") >> digit >> digit >> lit("-") >> digit >> digit >> digit >> digit >> lit("\n")]; count %= lexeme[lit("anzahl: ") >> +digit >> lit("\n")]; points %= lexeme[+digit >> lit("\t")]; mark %= lexeme[digit >> lit("\n")]; matnumber %= lexeme[(digit >> digit >> digit >> punct >> digit >> digit >> digit) >> lit("\t")]; student %= matnumber >> points >> mark; start %= subject >> dozent >> date >> count >> student;
that works fine, rule student brings problem have element 3 parts. matnumber, points, , mark. can imagine mean, here txt-file try parse:
subject: physics dozent: wayne datum: 20-10-2014 anzahl: 20 729.888 33 5 185.363 35 5
the last 2 lines rule student. , in txt-file have more these 2 lines.
that can take these lines "student" wrote vector in our struct typedef:
typedef boost::fusion::vector<string, string, string> student_t;
then use in our struct:
struct klausur { string str_subject; string str_dozent; string str_date; string count; string matr_nr; string points; string mark; string ende; student_t student; void tostring() { cout << "struct.fach: " << str_subject << endl; cout << "struct.dozent: " << str_dozent << endl; cout << "struct.datum: " << str_date << endl; cout << "struct.anzahl: " << count << endl; cout << "struct.mat_nr: " << matr_nr << endl; cout << "struct.punkte: " << points << endl; cout << "struct.note: " << mark << endl; cout << "struct.student<0>: " << vec::at_c<0>(student); cout << "struct.student<1>: " << vec::at_c<1>(student); cout << "struct.student<2>: " << vec::at_c<2>(student); } };
then have our boost_adapt_struct this:
boost_fusion_adapt_struct( client::klausur, (string, str_subject) (string, str_dozent) (string, str_date) (string, count) (string, matr_nr) (string, points) (string, mark) (student_t, student)
)
you see have typedef down there.
and have our rules in grammar.
qi::rule<iterator, string(), ascii::space_type> subject; qi::rule<iterator, string(), ascii::space_type> dozent; qi::rule<iterator, string(), ascii::space_type> date; qi::rule<iterator, string(), ascii::space_type> count; qi::rule<iterator, string(), ascii::space_type> matnumber; qi::rule<iterator, string(), ascii::space_type> points; qi::rule<iterator, string(), ascii::space_type> mark; qi::rule<iterator, boost::fusion::vector<boost::fusion::vector<std::string, std::string, std::string> >()> student;
and there final problem our project...
we don´t know datatype qi:rule needs boost_adapt... works fine it. other points strings, don´t know how implement own vector created.
all other rules working fine , in struct later vector makes problems.
has idea that? can upload more files , code-snippets if need, still think it´s maybe small problem can´t see. around many boost topics did not found right thing.
i have add info beginner, maybe did not explain right and... yeah. hope understand it. english not best...
thank in advance help.
william
spirit parser generator. don't seem parse (you "extract" character sequences, more tokenizing).
i'd this:
- use proper data types
- use
blank
skipping (doesn't includeeol
) - put
eol
expectation in right spot - put lexemes in right spot
- make
date_t
it's own type - make
student_t
it's own type - fix rule use
std::vector<student_t>()
instead of ~fusion::vector<student_t>()
(that mistake) - use
operator<<
printing - use
repeat(n) [ student >> eol ]
parse expected number of student lines - use
qi::locals
pass number of students expectedrepeat()
#define boost_spirit_debug #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/adapted/struct.hpp> #include <iostream> #include <iomanip> namespace qi = boost::spirit::qi; namespace vec = boost::fusion; struct student_t { std::string matr_nr; unsigned points; int mark; }; struct date_t { unsigned dd, mm, yyyy; friend std::ostream& operator<<(std::ostream& os, date_t const& d) { std::ostream local(os.rdbuf()); local << std::setw(2) << std::setfill('0') << d.dd << "-" << std::setw(2) << std::setfill('0') << d.mm << "-" << std::setw(4) << std::setfill('0') << d.yyyy; return os; } }; boost_fusion_adapt_struct(student_t, (std::string,matr_nr)(unsigned,points)(int,mark)) boost_fusion_adapt_struct(date_t, (unsigned,dd)(unsigned,mm)(unsigned,yyyy)) struct klausur { std::string str_subject; std::string str_dozent; date_t date; unsigned count; std::vector<student_t> students; friend std::ostream& operator<<(std::ostream& os, klausur const& k) { os << "fach: " << k.str_subject << '\n'; os << "dozent: " << k.str_dozent << '\n'; os << "datum: " << k.date << '\n'; os << "anzahl: " << k.count << '\n'; (auto& s : k.students) { os << "mat_nr: " << s.matr_nr << '\n'; os << "punkte: " << s.points << '\n'; os << "note: " << s.mark << '\n'; } return os; } }; boost_fusion_adapt_struct(klausur, (std::string , str_subject) (std::string , str_dozent) (date_t , date) (unsigned , count) (std::vector<student_t> , students) ) template <typename iterator, typename skipper = qi::ascii::blank_type> struct grammar : qi::grammar<iterator, klausur(), skipper> { grammar() : grammar::base_type(start) { using namespace qi; subject = "fach:" >> lexeme [ +~char_('\n') ] >> eol; dozent = "dozent:" >> lexeme [ +~char_('\n') ] >> eol; date = "datum:" >> lexeme [uint_ >> '-' >> uint_ >> '-' >> uint_] >> eol; count = "anzahl:" >> uint_ >> eol; points = uint_; mark = int_parser<int, 10, 1, 1>(); // single base-10 digit // no clue format; it? real number? matnumber = lexeme[digit >> digit >> digit >> punct >> digit >> digit >> digit]; student = matnumber >> points >> mark; _a_type expected; klausur_ %= subject >> dozent >> date >> count [ expected = _1 ] >> repeat(expected) [ student >> (eol|eoi) ] ; start = klausur_; boost_spirit_debug_nodes((start)(klausur_)(student)(matnumber)(mark)(points)(count)(date)(dozent)(subject)) } private: qi::rule<iterator, klausur(), skipper> start; qi::rule<iterator, klausur(), skipper, qi::locals<unsigned> > klausur_; qi::rule<iterator, std::string() , skipper> subject; qi::rule<iterator, std::string() , skipper> dozent; qi::rule<iterator, date_t(), skipper> date; qi::rule<iterator, unsigned() , skipper> count; qi::rule<iterator, std::string() , skipper> matnumber; qi::rule<iterator, unsigned() , skipper> points; qi::rule<iterator, int() , skipper> mark; qi::rule<iterator, student_t() , skipper> student; }; int main() { using = std::string::const_iterator; std::string const input = r"(fach: physics dozent: wayne datum: 20-10-2014 anzahl: 2 729.888 33 5 185.363 35 5)"; f = input.begin(), l = input.end(); grammar<it> g; klausur k; bool ok = qi::phrase_parse(f, l, g, qi::ascii::blank, k); if (ok) { std::cout << "parse success\n"; std::cout << k; } else { std::cout << "parse failed\n"; } if (f!=l) { std::cout << "remaining input: '" << std::string(f,l) << "'\n"; } }
output:
parse success fach: physics dozent: wayne datum: 20-10-2014 anzahl: 2 mat_nr: 729.888 punkte: 33 note: 5 mat_nr: 185.363 punkte: 35 note: 5
as 72 lines of debug output:
<start> <try>fach: physics\ndozent</try> <klausur_> <try>fach: physics\ndozent</try> <subject> <try>fach: physics\ndozent</try> <success>dozent: wayne\ndatum:</success> <attributes>[[p, h, y, s, i, c, s]]</attributes> </subject> <dozent> <try>dozent: wayne\ndatum:</try> <success>datum: 20-10-2014\nan</success> <attributes>[[w, a, y, n, e]]</attributes> </dozent> <date> <try>datum: 20-10-2014\nan</try> <success>anzahl: 2\n729.888 33</success> <attributes>[[20, 10, 2014]]</attributes> </date> <count> <try>anzahl: 2\n729.888 33</try> <success>729.888 33 5\n185.36</success> <attributes>[2]</attributes> </count> <student> <try>729.888 33 5\n185.36</try> <matnumber> <try>729.888 33 5\n185.36</try> <success> 33 5\n185.363 35 5</success> <attributes>[[7, 2, 9, ., 8, 8, 8]]</attributes> </matnumber> <points> <try> 33 5\n185.363 35 5</try> <success> 5\n185.363 35 5</success> <attributes>[33]</attributes> </points> <mark> <try> 5\n185.363 35 5</try> <success>\n185.363 35 5</success> <attributes>[5]</attributes> </mark> <success>\n185.363 35 5</success> <attributes>[[[7, 2, 9, ., 8, 8, 8], 33, 5]]</attributes> </student> <student> <try>185.363 35 5</try> <matnumber> <try>185.363 35 5</try> <success> 35 5</success> <attributes>[[1, 8, 5, ., 3, 6, 3]]</attributes> </matnumber> <points> <try> 35 5</try> <success> 5</success> <attributes>[35]</attributes> </points> <mark> <try> 5</try> <success></success> <attributes>[5]</attributes> </mark> <success></success> <attributes>[[[1, 8, 5, ., 3, 6, 3], 35, 5]]</attributes> </student> <success></success> <attributes>[[[p, h, y, s, i, c, s], [w, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes><locals>(2)</locals> </klausur_> <success></success> <attributes>[[[p, h, y, s, i, c, s], [w, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes> </start>
Comments
Post a Comment