31 #include <boost/spirit/include/qi.hpp> 32 #include <boost/spirit/include/phoenix.hpp> 33 #include <boost/fusion/adapted.hpp> 43 typedef boost::variant<std::string, std::vector<std::string>> FieldVal_t;
44 typedef boost::optional<std::string> Lang_t;
51 typedef std::vector<Field> Fields_t;
58 typedef std::vector<Group> Groups_t;
89 namespace ascii = boost::spirit::ascii;
90 namespace qi = boost::spirit::qi;
91 namespace phoenix = boost::phoenix;
93 template<
typename Iter>
94 struct Parser : qi::grammar<Iter, File ()>
96 qi::rule<Iter, File ()> Start_;
97 qi::rule<Iter, Group ()> Group_;
98 qi::rule<Iter, std::string ()> GroupName_;
99 qi::rule<Iter, std::string ()>
Lang_;
100 qi::rule<Iter, void ()> KeyValSep_;
101 qi::rule<Iter, std::string ()> LineValSingle_;
102 qi::rule<Iter, FieldVal_t ()> LineVal_;
103 qi::rule<Iter, Field ()> Line_;
104 qi::rule<Iter, void ()> Comment_;
107 : Parser::base_type (Start_)
109 auto eol = qi::lit (
"\n");
110 Comment_ %= qi::lit (
"#") >> *(qi::char_ -
'\r' -
'\n') >> eol;
112 Lang_ %=
'[' >> qi::lexeme [+(qi::char_ (
"a-zA-Z0-9@_-"))] >>
']';
114 KeyValSep_ %= *(qi::lit (
' ')) >>
'=' >> *(qi::lit (
' '));
116 LineValSingle_ %= qi::lexeme [+((qi::lit (
"\\;") | (qi::char_ -
';' -
'\r' -
'\n')))];
117 LineVal_ %= ((LineValSingle_ %
';') >> -qi::lit (
";")) | LineValSingle_;
119 Line_ %= qi::lexeme [+(qi::char_ (
"a-zA-Z0-9-"))] >>
125 GroupName_ %=
'[' >> qi::lexeme [+(qi::char_ (
"a-zA-Z0-9 "))] >>
']';
127 Group_ %= GroupName_ >> eol >>
128 *(Comment_ | Line_ | eol);
130 Start_ %= *Comment_ >> +Group_;
132 qi::on_error<qi::fail> (Start_,
133 std::cout << phoenix::val (
"Error! Expecting") << qi::_4
134 << phoenix::val (
" here: \"") << phoenix::construct<std::string> (qi::_3, qi::_2)
135 << phoenix::val (
"\"") << std::endl);
139 template<
typename Iter>
140 File Parse (Iter begin, Iter end)
143 qi::parse (begin, end, Parser<Iter> (), res);
147 QString ToUtf8 (
const std::string& str)
149 return QString::fromUtf8 (str.c_str ());
152 struct ValGetter :
public boost::static_visitor<QStringList>
154 QStringList operator() (
const std::string& str)
const 156 return QStringList (ToUtf8 (str));
159 QStringList operator() (
const std::vector<std::string>& vec)
const 162 std::transform (vec.begin (), vec.end (), std::back_inserter (result), ToUtf8);
170 const auto& file = Parse (data.begin (), data.end ());
173 for (
const auto& item : file.Groups_)
176 for (
const auto& field : item.Fields_)
178 const auto& values = boost::apply_visitor (ValGetter (), field.Val_);
179 const auto& lang = field.Lang_ ? ToUtf8 (*field.Lang_) : QString ();
180 group [ToUtf8 (field.Name_)] [lang] = values;
182 result [ToUtf8 (item.Name_)] = group;
BOOST_FUSION_ADAPT_STRUCT(Student, ID_, Name_) struct StudentInfo
UTIL_XDG_API Result_t operator()(const QByteArray &data)
Parses the XDG data.