Использование boost-spirit для разбора строки на структуру QStrings - PullRequest
0 голосов
/ 07 июня 2019

Сегодня я попытался написать очень простой парсер, используя 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;
    }
}
...