本文介绍了在语义动作中添加到精神气符号表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

转到 boost :: spirit :: qi :: symbols文档,我认为从语义动作向qi :: symbols添加符号并不难.不幸的是,它似乎没有我想象的那么简单.

Going by the opening paragraph of the boost::spirit::qi::symbols documentation, I assumed that it wouldn't be too hard to add symbols to a qi::symbols from a semantic action. Unfortunately it appears to be not as straightforward as I would have assumed.

下面的测试代码出现了问题:

The following bit of test code exhibits the problem:

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;

typedef qi::symbols<char, unsigned int> constants_dictionary;

template <typename Iter> struct parser : public qi::grammar<Iter, qi::space_type> {

    parser(constants_dictionary &dict) : parser::base_type(start) {

        start = qi::lit("@") >> ((+qi::char_) >> qi::uint_)[dict.add(qi::_1, qi::_2)];
    }

    qi::rule<Iter> start;
};

int main() {
    constants_dictionary dict;
    parser<std::string::const_iterator> prsr(dict);
    std::string test = "@foo 3";
    parse(test.begin(), test.end(), prsr, qi::space);
}

在VS2010中给出与qi :: _ 2相关的类型错误:

Gives type errors related to qi::_2 from VS2010:

C:\Users\k\Coding\dashCompiler\spirit_test.cpp(12) : error C2664: 'const boost::
spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::o
perator ()<boost::spirit::_1_type>(const Str &,const T &) const' : cannot conver
t parameter 2 from 'const boost::spirit::_2_type' to 'const unsigned int &'
        with
        [
            Char=char,
            T=unsigned int,
            Str=boost::spirit::_1_type
        ]
        Reason: cannot convert from 'const boost::spirit::_2_type' to 'const uns
igned int'
        No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called
        C:\Users\k\Coding\dashCompiler\spirit_test.cpp(10) : while compiling cla
ss template member function 'parser<Iter>::parser(constants_dictionary &)'
        with
        [
            Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
        ]
        C:\Users\k\Coding\dashCompiler\spirit_test.cpp(21) : see reference to cl
ass template instantiation 'parser<Iter>' being compiled
        with
        [
            Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
        ]

(讨厌的VS2010错误样式的道歉)

(Apologies for the nasty VS2010 error-style)

我应该使用哪种语法在此表中添加(然后删除)符号?

What syntax am I supposed to be using to add (and later on, remove) symbols from this table?

推荐答案

此问题之前已得到答复.但是,您发布的代码存在很多问题,因此,我将一一解决它们,以免您不必要地盯着错误消息页面.

This question has been answered before. However, there is quite a range of problems with your posted code, so I'll fix them up one by one to spare you unnecessary staring at pages of error messages.

工作代码(加上输出验证)为 在liveworkspace.org上 .

The working code (plus verification of output) is here on liveworkspace.org.

注意:

  1. 语义动作必须是Phoenix actor ,即您需要

  • boost::bindphoenix::bindstd::bind
  • phoenix::lambda<>phoenix::function<>
  • 函数指针或多态可调用对象(根据文档)

  • boost::bind, phoenix::bind, std::bind
  • phoenix::lambda<> or phoenix::function<>
  • a function pointer or polymorphic calleable object (as per the documentation)

我建议phoenix::bind(在这种情况下),我在下面显示

I'd recommend phoenix::bind (in this particular case), which I show below


#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

typedef qi::symbols<char, unsigned int> constants_dictionary;

template <typename Iter> struct parser : qi::grammar<Iter, qi::space_type> 
{
    parser(constants_dictionary &dict) : parser::base_type(start) 
    {
        start = qi::lit("@") >> (qi::lexeme [+qi::graph] >> qi::uint_)
            [ phx::bind(dict.add, qi::_1, qi::_2) ]
            ;
    }

    qi::rule<Iter, qi::space_type> start;
};

int main() {
    constants_dictionary dict;
    parser<std::string::const_iterator> prsr(dict);
    const std::string test = "@foo 3";

    if (qi::phrase_parse(test.begin(), test.end(), prsr, qi::space))
    {
        std::cout << "check: " << dict.at("foo") << "\n";
    }
}

这篇关于在语义动作中添加到精神气符号表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 13:10