boost qi::grammar 不使用 spirit/phoenix 更新值类型

boost qi::grammar not updating valuetype using spirit/phoenix

我有以下问题:

在使用 qi::grammar 解析文本时,结构语法不返回已解析对象的值。

语法

template<typename Iterator>
struct PositionalDegreeImpl_grammer : qi::grammar<Iterator,PositionalDegreeImpl>
{

    struct Type_ : qi::symbols<char,horus::parsergenerator::nmea::CardinalDirection::Direction>
    {
        Type_()
        {
            this->add("E", horus::parsergenerator::nmea::CardinalDirection::Direction::EAST)
                    ("N",  horus::parsergenerator::nmea::CardinalDirection::Direction::NORTH)
                    ("W",  horus::parsergenerator::nmea::CardinalDirection::Direction::WEST)
                    ("S",  horus::parsergenerator::nmea::CardinalDirection::Direction::SOUTH);
        }
    } type_;

    qi::rule<Iterator,PositionalDegreeImpl> r;
    PositionalDegreeImpl_grammer() : PositionalDegreeImpl_grammer::base_type(r)
    {
        r = (double_ >> ',' >> type_)

                [
                   qi::_val = boost::phoenix::construct<PositionalDegreeImpl>(qi::_2,qi::_1)
                ];
    }

};

在调试会话期间可以看到使用正确的值调用了正确的构造函数。

std::string str = "123.2,W";  
PositionalDegreeImpl val(horus::parsergenerator::nmea::CardinalDirection::Direction::EAST,1.0);


PositionalDegreeImpl_grammer<std::string::iterator> pos_deg_parser;
bool r = qi::parse(str.begin(), str.end(), pos_deg_parser, &val);

if (!r || val.degrees() != 123.2)
{
    std::cout<< "Err" <<std::endl;
}

val 包含解析后的初始值。我有一种感觉,我正在看东西。

纯虚拟基地

class PositionalDegree
{
public:
    /*! number of degrees of the position */
    virtual double degrees() const = 0;

    /*! the direction {N,S,E,W} of the position */
    virtual const CardinalDirection& direction() const = 0;

    /*! Provide the assignment operator */
    virtual PositionalDegree& operator=(const PositionalDegree&) = 0;
};

实施

class PositionalDegreeImpl : public PositionalDegree
{
private:
    double _degrees;
    CardinalDirectionImpl _direction;
public:
    PositionalDegreeImpl();
    explicit PositionalDegreeImpl(PositionalDegree const &other);
    PositionalDegreeImpl(PositionalDegreeImpl const &other);
    PositionalDegreeImpl(CardinalDirectionImpl const & cardinal, double degrees);


    virtual ~PositionalDegreeImpl();

    virtual double degrees() const;

    virtual const CardinalDirection& direction() const;

    virtual PositionalDegree& operator=(const PositionalDegree& other);
    PositionalDegreeImpl& operator=(const PositionalDegreeImpl& other);

};

如有任何想法和提示,我们将不胜感激。

问候奥克

看来您缺少括号:

qi::rule<Iterator,PositionalDegreeImpl()> r;

如果我没记错的话,包含括号的绝对要求将在即将发布的版本中取消(可能已经存在 1_57_0

这是一个独立的例子

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

namespace horus { namespace parsergenerator { namespace nmea {

    struct CardinalDirection {
        enum class Direction { EAST, NORTH, WEST, SOUTH };
    };

    struct PositionalDegreeImpl {
        PositionalDegreeImpl(CardinalDirection::Direction direction, double d)
         : _dir(direction), _degrees(d)
        {
        }

        double degrees() const { return _degrees; }

      private:
        CardinalDirection::Direction _dir;
        double _degrees;
    };

    template<typename Iterator, typename T = PositionalDegreeImpl>
    struct PositionalDegreeGrammar : qi::grammar<Iterator,T()>
    {
        PositionalDegreeGrammar() : PositionalDegreeGrammar::base_type(r)
        {
            r = (qi::double_ >> ',' >> type_)
                [
                    qi::_val = boost::phoenix::construct<T>(qi::_2,qi::_1)
                ];
        }
      private:
        struct Type_ : qi::symbols<char, CardinalDirection::Direction> {
            Type_() {
                this->add
                    ("E", CardinalDirection::Direction::EAST)
                    ("N",  CardinalDirection::Direction::NORTH)
                    ("W",  CardinalDirection::Direction::WEST)
                    ("S",  CardinalDirection::Direction::SOUTH);
            }
        } type_;

        qi::rule<Iterator,T()> r;
    };

} } }

int main() 
{
    using namespace horus::parsergenerator::nmea;
    typedef std::string::const_iterator It;

    PositionalDegreeImpl val(CardinalDirection::Direction::EAST, 1.0);

    PositionalDegreeGrammar<It> pos_deg_parser;

    std::string const str = "123.2,W";  
    It f = str.begin(), l = str.end();

    bool r = qi::parse(f, l, pos_deg_parser, val);

    if (r)
        std::cout << val.degrees() << ": " << std::boolalpha << (123.2==val.degrees()) << "\n";
    else
        std::cout << "parsing failed\n";
}

打印:

123.2: true