gpt4 book ai didi

c++ - 如果我的语法中有 "or"('|' ),如何使用 boost spirit 将数据解析为 C++ Struct

转载 作者:搜寻专家 更新时间:2023-10-31 02:23:43 25 4
gpt4 key购买 nike

我有以下 C++ 结构:

struct Dimension {
enum Type { PARENT, CHILD, PIXEL };

Type mWidth_type = Type::PIXEL;
int mWidth = 0;

Type mHeight_type = Type::PIXEL;
int mHeight = 0;
};

我的语法是这样的:

+(char_ - "{") >> "{" >>
-(lit("width") >> ":" >> (int_ | lit("_parent") | lit("_child")) >> ";") >>
-(lit("height") >> ":" >> (int_ | lit("_parent") | lit("_child")) >> ";") >>
"}"

我有一个层次结构,其中一些节点可能采用父节点或子节点的宽度或/和高度。所以在我的逻辑中,我首先检查每个节点的 Dimension 类型。如果它是 PIXEL,我得到值,否则我从父节点或子节点询问值。因此,在我的文件中,我可以有以下可能性(高度相同):

width: 10;

在这种情况下,我想使用默认枚举 PIXEL 保留类型并设置 mWidth 的值。

widht: _parent;

在这种情况下,我想将 Type 设置为 PARENT 并将 mWidth 保留为默认值 0。

width: _child;

在这种情况下,我想将 Type 设置为 CHILD 并将 mWidth 保留为默认值 0。

如何将其解析为结构?如果我的尺寸只能采用数字,那么我就可以继续,但我被卡住了,因为这是一个不同的情况。非常感谢任何提示、想法和帮助!

编辑1:

下面是需要解析成上述结构的文本文件示例:

.struct1 {
width: 12;
height: 50;
}

.struct2 {
width: _parent;
height: 50;
}

.struct3 {
width: 40;
height: _child;
}

.struct4 {
width: _parent;
height: _child;
}

最佳答案

我建议考虑 AST 类型,以免重复自己:

struct Dimension {
struct Value {
enum Type { PARENT, CHILD, PIXEL } type;
int value;

friend std::ostream& operator<<(std::ostream& os, Value const& v) {
switch(v.type) {
case PARENT: return os << "[PARENT:" << v.value << "]";
case CHILD: return os << "[CHILD:" << v.value << "]";
case PIXEL: return os << "[PIXEL:" << v.value << "]";
}
return os << "?";
}
};

Value mWidth, mHeight;
};

适应融合:

BOOST_FUSION_ADAPT_STRUCT(Dimension::Value, (Dimension::Value::Type, type)(int, value))
BOOST_FUSION_ADAPT_STRUCT(Dimension, (Dimension::Value, mWidth)(Dimension::Value, mHeight))

现在,我将编写语法来匹配:

    start   = width_ ^ height_;
width_ = lit("width") >> ':' >> value_ >> ';';
height_ = lit("height") >> ':' >> value_ >> ';';

value_ =
( "_child" >> attr(Dimension::Value::CHILD) >> attr(0)
| "_parent" >> attr(Dimension::Value::PARENT) >> attr(0)
| eps >> attr(Dimension::Value::PIXEL) >> int_
);

注意:

  • 您可以使用置换解析器来实现更多功能
  • 你可以看到attr的使用注入(inject)属性,以便所有分支都合成一个 vector2<Type, int>

添加调试和一些测试用例:

Live On Coliru

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

namespace qi = boost::spirit::qi;

struct Dimension {
struct Value {
enum Type { PARENT, CHILD, PIXEL } type;
int value;

friend std::ostream& operator<<(std::ostream& os, Value const& v) {
switch(v.type) {
case PARENT: return os << "[PARENT:" << v.value << "]";
case CHILD: return os << "[CHILD:" << v.value << "]";
case PIXEL: return os << "[PIXEL:" << v.value << "]";
}
return os << "?";
}
};

Value mWidth, mHeight;
};

BOOST_FUSION_ADAPT_STRUCT(Dimension::Value, (Dimension::Value::Type, type)(int, value))
BOOST_FUSION_ADAPT_STRUCT(Dimension, (Dimension::Value, mWidth)(Dimension::Value, mHeight))

template <typename It, typename Skipper>
struct grammar : qi::grammar<It, Dimension(), Skipper>
{
grammar() : grammar::base_type(start) {
using namespace qi;

start = width_ ^ height_;
width_ = lit("width") >> ':' >> value_ >> ';';
height_ = lit("height") >> ':' >> value_ >> ';';
value_ =
( "_child" >> attr(Dimension::Value::CHILD) >> attr(0)
| "_parent" >> attr(Dimension::Value::PARENT) >> attr(0)
| eps >> attr(Dimension::Value::PIXEL) >> int_
);

BOOST_SPIRIT_DEBUG_NODES((start)(value_)(width_)(height_))
}
private:
qi::rule<It, Dimension(), Skipper> start;
qi::rule<It, Dimension::Value(), Skipper> value_, width_, height_;
};

int main() {
using It = std::string::const_iterator;
grammar<It, qi::space_type> p;

for (std::string const input : {
"width: 10; height: _child;",
"width: _parent; height: 10;",
"width: _child; height: 10;"
})
{
It f = input.begin(), l = input.end();
std::cout << "\n-----------------------------------\n"
<< "Parsing '" << input << "'\n";

Dimension parsed;
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);

if (ok)
std::cout << "Parsed: (" << parsed.mWidth << "x" << parsed.mHeight << ")\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}

输出(无调试信息):

-----------------------------------
Parsing 'width: 10; height: _child;'
Parsed: ([PIXEL:10]x[CHILD:0])

-----------------------------------
Parsing 'width: _parent; height: 10;'
Parsed: ([PARENT:0]x[PIXEL:10])

-----------------------------------
Parsing 'width: _child; height: 10;'
Parsed: ([CHILD:0]x[PIXEL:10])

关于c++ - 如果我的语法中有 "or"('|' ),如何使用 boost spirit 将数据解析为 C++ Struct,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28976049/

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