Сегодня я попытался написать очень простой парсер, используя boost-spirit
.
Теперь я наткнулся на препятствия, которые я действительно не знаю, как решить.
По сути, я хотел, чтобы семантическое действие возвращало QString
вместо Stl std::string
. И я также хотел сделать это преобразование очень простым способом прямо в семантическом действии, так как будет еще больше объектов QString
. Конечная цель - упаковать все эти строки QString в общую структуру.
(QString - эквивалент Qt-Framework для std::string
).
Это то, что я получил до сих пор.
#include <QString>
#include <vector>
#include <iostream>
#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/phoenix/object/construct.hpp>
class QStringHelper {
public:
QStringHelper() {}
QStringHelper(const std::string& string) : mString(QString::fromStdString(string)){
}
// This operator might help?
QString operator()() const {
return mString;
}
QString mString;
};
template <typename Iterator, typename Skipper>
struct grammar : boost::spirit::qi::grammar<Iterator, void(), Skipper>
{
QString color;
std::string stdColor;
QStringHelper helper;
grammar() : grammar::base_type(listOfProperties)
{
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using qi::lit;
using qi::lexeme;
using ascii::char_;
using ascii::string;
using boost::phoenix::ref;
using namespace qi::labels;
listOfProperties = (colorProperty % lit(";"));
// 1. Works, but is not what I desire!
// colorProperty = lit("color") >> lit(":") >> qi::as_string[lexeme[+(char_ - ';')]][boost::phoenix::ref(stdColor) =_1];
// 2. Cannot compile, as QString has not constructor like QString(const std::string&)
// colorProperty = lit("color") >> lit(":") >> qi::as_string[lexeme[+(char_ - ';')]][boost::phoenix::ref(color) = boost::phoenix::construct<QString>(_1)];
// 3. Does compile, but is not exactly what I desire!
colorProperty = lit("color") >> lit(":") >> qi::as_string[lexeme[+(char_ - ';')]][boost::phoenix::ref(helper) = boost::phoenix::construct<QStringHelper>(_1)];
// 4. My desired solution, that I really don't know what someMagicExpression might be?
// colorProperty = lit("color") >> lit(":") >> qi::as_string[lexeme[+(char_ - ';')]][boost::phoenix::ref(color) = someMagicExpression(_1)];
// Many more complex properties will go by!
}
boost::spirit::qi::rule<Iterator, void(), Skipper> listOfProperties;
boost::spirit::qi::rule<Iterator, void(), Skipper> colorProperty;
};
int main(int argc, char**args) {
try {
std::string stringToParse = "color:#ff00ff";
boost::spirit::qi::space_type space;
grammar<std::string::const_iterator, decltype(space)> parser;
auto b = stringToParse.begin();
auto e = stringToParse.end();
bool ok = boost::spirit::qi::phrase_parse(b, e, parser, space);
if (b != e) {
return EXIT_SUCCESS;
}
else {
std::cout << "Color: " << parser.color.toStdString();
}
return EXIT_SUCCESS;
}
catch (const boost::spirit::qi::expectation_failure<std::string::iterator>&) {
return EXIT_FAILURE;
}
}