子解析器属性

用户名

我在编写语法时遇到麻烦。假设我有一个Derived继承自的类BaseGrammarDerived具有Derived综合属性,而GrammarBase具有Base综合属性。如何GrammarBaseGrammarDerived解析规则中使用?我认为这应该可行,因为我可以将a绑定Base &到a,Derived &但似乎没有任何效果。

换句话说,我如何通过下面的参考grammarBase与之互动_val

template<typename Iterator>
struct GrammarDerived : public grammar <Iterator, Derived()> {
    GrammarDerived() : GrammarDerived::base_type(start) {
        start = rule1[bind(someFunc, _val)] >> grammarBase;
        rule1 = /* ... */;
    }
    rule<Iterator, Derived()> start;
    rule<Iterator, Derived()> rule1;
    GrammarBase grammarBase;
};

在一个更简单的设置中,这显示了它在很大程度上主要是类型推导的限制:

Derived parse_result;
bool ok = qi::phrase_parse(f, l, base_, qi::space, data);

在解析器公开Base时将不起作用,但是您可以使用模板实例[1]的“类型提示”来修复它

bool ok = qi::phrase_parse(f, l, base_, qi::space, static_cast<Base&>(data));

完整演示Live On Coliru

#include <algorithm>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

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

struct Base {
    int x;
    double y;
};

BOOST_FUSION_ADAPT_STRUCT(Base, (int,x)(double,y))

struct Derived : Base { };

int main()
{
    typedef std::string::const_iterator It;
    qi::rule<It, Base(), qi::space_type> base_ = qi::int_ >> qi::double_;

    std::string const input = "1 3.14";
    auto f(input.begin()), l(input.end());

    Derived parse_result;
    bool ok = qi::phrase_parse(f, l, base_, qi::space, static_cast<Base&>(parse_result));
    if (ok)
    {
        std::cout << "Parsed: " << parse_result.x << " " << parse_result.y << "\n";
    } else
    {
        std::cout << "Parse failed\n";
    }

    if (f != l)
    {
        std::cout << "Input remaining: '" << std::string(f,l) << "'\n";
    }
}

或者

您可以通过将对exposable属性的引用显式传递给基本解析器/规则来避免混淆:

template <typename It, typename Skipper = qi::space_type>
struct derived_grammar : qi::grammar<It, Derived(), Skipper>
{
    derived_grammar() : derived_grammar::base_type(start) {
        base_ = qi::int_ >> qi::double_;
        glue_ = base_ [ qi::_r1 = qi::_1 ];
        start = "derived:" >> glue_(qi::_val); // passing the exposed attribute for the `Base&` reference
    }
  private:
    qi::rule<It, Derived(),   Skipper> start;
    qi::rule<It, void(Base&), Skipper> glue_;
    qi::rule<It, Base(),      Skipper> base_; // could be a grammar instead of a rule
};

如果您真的坚持,可以不使用glue_/base_分隔qi::attr_cast<Base, Base>而这样做(但是为了清晰起见,我不会这样做)。

再次提供完整代码,以供参考Live On Coliru

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <algorithm>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

struct Base {
    int x;
    double y;
};

BOOST_FUSION_ADAPT_STRUCT(Base, (int,x)(double,y))

struct Derived : Base { };

template <typename It, typename Skipper = qi::space_type>
struct derived_grammar : qi::grammar<It, Derived(), Skipper>
{
    derived_grammar() : derived_grammar::base_type(start) {
        base_ = qi::int_ >> qi::double_;
        glue_ = base_ [ qi::_r1 = qi::_1 ];
        start = "derived:" >> glue_(qi::_val); // passing the exposed attribute for the `Base&` reference
    }
  private:
    qi::rule<It, Derived(),   Skipper> start;
    qi::rule<It, void(Base&), Skipper> glue_;
    qi::rule<It, Base(),      Skipper> base_; // could be a grammar instead of a rule
};

int main()
{
    typedef std::string::const_iterator It;
    derived_grammar<It> g;

    std::string const input = "derived:1 3.14";
    auto f(input.begin()), l(input.end());

    Derived parse_result;
    bool ok = qi::phrase_parse(f, l, g, qi::space, parse_result);
    if (ok)
    {
        std::cout << "Parsed: " << parse_result.x << " " << parse_result.y << "\n";
    } else
    {
        std::cout << "Parse failed\n";
    }

    if (f != l)
    {
        std::cout << "Input remaining: '" << std::string(f,l) << "'\n";
    }
}

[1]参考实例化功能模板 qi::phrase_parse这里

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章