Boost spirit using local variables

跟風遠走 提交于 2019-12-02 02:34:45
sehe
    if(ref(is_int)()) {

here you evaluate condition during construction. This is not how it works. The rule will always take the same branch.

Instead, look at the Nabialek trick: http://boost-spirit.com/home/articles/qi-example/nabialek-trick/

Here's the full Nabialek Trick applied to your sample Live On Coliru:

  1. you needed to make std::cout << "int" lazy actors (by wrapping at least phx::ref(std::cout) or phx::val("int") as a Phoenix Actor)

  2. you still have no use for the attribute propagation (std::string()) since it is disabled in the presence of Semantic Actions (see the previous answer). You can propagate values from Nabialek subrules, though:

#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 spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
using boost::phoenix::ref;


template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, ascii::space_type, qi::locals<qi::rule<Iterator, ascii::space_type>*> >
{
public:
    x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
    {
        using namespace qi;

        int_rule = int_   [std::cout << phx::val("int ") << _1 << ".\n"];
        dbl_rule = double_[std::cout << phx::val("double ") << _1 << ".\n"];
        subrules.add
            ("I", &int_rule)
            ("D", &dbl_rule);

        start_rule = subrules[_a = _1] >> lazy(*_a);
    }
private:
    typedef qi::rule<Iterator, ascii::space_type> subrule;

    qi::symbols<char, subrule*> subrules;
    qi::rule<Iterator, ascii::space_type, qi::locals<subrule*> > start_rule;
    qi::rule<Iterator, ascii::space_type> int_rule, dbl_rule;
};

int main()
{
    typedef std::string::const_iterator iter;
    std::string storage("I 5");
    iter it_begin(storage.begin());
    iter it_end(storage.end());
    using boost::spirit::ascii::space;
    x_grammar<iter> g;
    try {
        bool r = qi::phrase_parse(it_begin, it_end, g, space);
        if (r) {
            std::cout << "Pass!\n";
        }
        else {
            std::cout << "Fail!\n";
        }
    }
    catch (const qi::expectation_failure<iter>&) {
        std::cout << "Fail!\n";
    }
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!