今天,我尝试使用boost-spirit
编写一个非常简单的解析器。
现在,我偶然遇到了一个障碍,我真的不知道该如何解决。
基本上,我希望语义操作返回QString
而不是Stl std::string
。我还想在语义动作中以非常简单的方式进行这种转换,因为将会有更多的QString
对象通过。最终目标是将所有这些QString打包到一个通用结构中。
(QString是std::string
的Qt-Framework等效项。)
这是我到目前为止所得到的。
#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;
}
}