gpt4 book ai didi

c++ - 子解析器属性

转载 作者:太空狗 更新时间:2023-10-29 21:42:36 24 4
gpt4 key购买 nike

我在编写语法时遇到问题。假设我有一个继承自 Base 的类 DerivedGrammarDerived 具有 Derived 综合属性,而 GrammarBase 具有 Base 综合属性。如何在 GrammarDerived 解析规则中使用 GrammarBase?我觉得这应该是可能的,因为我可以将 Base & 绑定(bind)到 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";
}
}

或者

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

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这里

关于c++ - 子解析器属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25696641/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com