Add to a spirit qi symbol table in a semantic action

╄→гoц情女王★ 提交于 2019-12-01 20:53:18
sehe

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.

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

Notes:

  1. the semantic action must be a Phoenix actor, i.e. you need

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

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

  2. There was a mismatch between the parser's skipper and the start rule
  3. qi::char_ eats all characters. Combined with the skipper, this resulted in parse failure, because (obviously) the digits in the value were also being eaten by +qi::char_. I show you one of many solutions, based on qi::lexeme[+qi::graph]
  4. use qi::lexeme to 'bypass' the skipper (i.e. to prevent +qi::graph to cut across whitespace because the skipper, well, skipped it)
  5. qi::parse doesn't take a skipper; use qi::phrase_parse for that (the reason it appeared to work is that any trailing 'variadic' arguments are bound to the exposed attributes of the parser, which in this case are unspecified, and therefore qi::unused_type).
  6. if you want to pass test.begin() and test.end() directly to qi::phrase_parse, you need to make it clear that you want const iterators. The more typical solution would be to introduce explicitely typed variables (first and last, e.g.)


#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";
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!