<tfoot id='OgZgH'></tfoot>
    • <bdo id='OgZgH'></bdo><ul id='OgZgH'></ul>
      <legend id='OgZgH'><style id='OgZgH'><dir id='OgZgH'><q id='OgZgH'></q></dir></style></legend>

        <small id='OgZgH'></small><noframes id='OgZgH'>

        <i id='OgZgH'><tr id='OgZgH'><dt id='OgZgH'><q id='OgZgH'><span id='OgZgH'><b id='OgZgH'><form id='OgZgH'><ins id='OgZgH'></ins><ul id='OgZgH'></ul><sub id='OgZgH'></sub></form><legend id='OgZgH'></legend><bdo id='OgZgH'><pre id='OgZgH'><center id='OgZgH'></center></pre></bdo></b><th id='OgZgH'></th></span></q></dt></tr></i><div id='OgZgH'><tfoot id='OgZgH'></tfoot><dl id='OgZgH'><fieldset id='OgZgH'></fieldset></dl></div>

      1. Boost Spirit x3:解析为结构体

        时间:2023-07-20

          • <bdo id='9y69Y'></bdo><ul id='9y69Y'></ul>

            <small id='9y69Y'></small><noframes id='9y69Y'>

              <tbody id='9y69Y'></tbody>

              <tfoot id='9y69Y'></tfoot>
            • <i id='9y69Y'><tr id='9y69Y'><dt id='9y69Y'><q id='9y69Y'><span id='9y69Y'><b id='9y69Y'><form id='9y69Y'><ins id='9y69Y'></ins><ul id='9y69Y'></ul><sub id='9y69Y'></sub></form><legend id='9y69Y'></legend><bdo id='9y69Y'><pre id='9y69Y'><center id='9y69Y'></center></pre></bdo></b><th id='9y69Y'></th></span></q></dt></tr></i><div id='9y69Y'><tfoot id='9y69Y'></tfoot><dl id='9y69Y'><fieldset id='9y69Y'></fieldset></dl></div>

                  <legend id='9y69Y'><style id='9y69Y'><dir id='9y69Y'><q id='9y69Y'></q></dir></style></legend>
                  本文介绍了Boost Spirit x3:解析为结构体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  来自 Boost Spirit X3 教程:

                  From the Boost Spirit X3 tutorial:

                  首先,让我们创建一个代表员工的结构体:

                  First, let's create a struct representing an employee:

                  namespace client { namespace ast
                  {
                     struct employee
                     {
                         int age;
                         std::string surname;
                         std::string forename;
                         double salary;
                     };
                  }}
                  

                  然后,我们需要将我们的员工结构告诉 Boost.Fusion 以使其成为语法可以利用的一流融合公民.

                  Then, we need to tell Boost.Fusion about our employee struct to make it a first-class fusion citizen that the grammar can utilize.

                  BOOST_FUSION_ADAPT_STRUCT(
                      client::ast::employee,
                      (int, age)
                      (std::string, surname)
                      (std::string, forename)
                      (double, salary)
                  )`
                  

                  [...]在fusion 看来,结构体只是元组的一种形式.你可以适应任何struct 是一个完全符合的融合元组.[...]应用我们上面的折叠规则,RHS 具有以下属性:fusion::vector结构员工与融合::矢量.所以,start 的 RHS 就地使用了 start 的属性(一个结构体员工)当它开始工作时.

                  [...] In fusion's view, a struct is just a form of a tuple. You can adapt any struct to be a fully conforming fusion tuple. [...] Applying our collapsing rules above, the RHS has an attribute of: fusion::vector<int, std::string, std::string, double> The struct employee IS compatible with fusion::vector. So, the RHS of start uses start's attribute (a struct employee) in-situ when it does its work.

                  如果我很好理解,这个逻辑在很大程度上依赖于属性的顺序.

                  If I well understood, this logic heavily relies on the order of the attributes.

                  现在,我需要解析类似的东西

                  Now, I am in a situation where I need to parse something like

                  Layer "L1" {
                      number = 23
                      color = green
                      visible = true
                  }
                  

                  结构化

                  struct LayerInfo
                  {
                      std::string layerName;
                      int layerNumber;
                      std::string color;
                      bool visible;
                  }
                  

                  问题是,图层属性的顺序可以改变,这与上面看到的逻辑相反.

                  The problem is, the order of the layer properties can change, which is in opposition with the logic seen above.

                  解析这样的结构的正确方法是什么?我是否一定需要使用语义动作?

                  Which is the correct way to parse into a struct like this? Do I need necessarily need to use semantic actions?

                  推荐答案

                  我喜欢@llonesmiz 在评论中的方法.

                  I love @llonesmiz's approach in the comment.

                  不过,我不得不"尝试使用 X3 的我最喜欢的方法,也使用函数组合.这是解析和传播值的方法的草图.

                  I "had to" try my favorite approach with X3 using functional composition too, though. Here's a sketch of the approach which does parse and propagate the values.

                  缺少对属性存在/唯一性的检查.(我认为这样的事情可以使用 x3::with<> 上下文添加来实现,它基本上包含一个 std::set<VT::*>.当然,这样的事情需要(依赖于实现?)强制转换或擦除包装器).

                  Missing are checks on property presence/uniqueness. (I think such a thing is doable using a x3::with<> context addition that basically contains a std::set<V T::*>. Of course such a thing needs (implementation dependent?) casts or an erasure wrapper).

                  暂时不加评论:

                  生活在 Coliru

                  #include <iostream>
                  //#define BOOST_SPIRIT_X3_DEBUG
                  #include <boost/spirit/home/x3.hpp>
                  #include <boost/fusion/include/adapt_struct.hpp>
                  #include <boost/fusion/include/io.hpp>
                  
                  struct LayerInfo
                  {
                      std::string layerName;
                      int layerNumber = 0;
                      std::string color;
                      bool visible = false;
                  };
                  
                  namespace Parser {
                      namespace x3 = boost::spirit::x3;
                  
                      // custom type parsers
                      auto quoted = rule<std::string>("quoted", x3::lexeme [ '"' >> *('\' >> x3::char_ | ~x3::char_('"')) >> '"' ]);
                      struct colors_type : x3::symbols<char> {
                          colors_type() {
                              this->add("red")("blue")("green")("black");
                          }
                      } static const colors;
                  
                      namespace detail {
                          template <typename T> auto propagate(T member) {
                              return [=](auto& ctx){ x3::traits::move_to(x3::_attr(ctx), x3::_val(ctx).*member); };
                          }
                  
                          template <typename T> auto make_member_parser(int T::* const member) { return x3::int_ [propagate(member)]; }
                          template <typename T> auto make_member_parser(bool T::* const member) { return x3::bool_ [propagate(member)]; }
                          template <typename T> auto make_member_parser(std::string T::* const member) { return x3::raw[colors] [propagate(member)]; }
                  
                          template <typename T = LayerInfo, typename P>
                              auto rule(const char* debug, P p) { return x3::rule<struct _, T> {debug} = x3::skip(x3::space)[p]; };
                  
                          auto property = [](auto label, auto member) {
                              return rule(label, x3::as_parser(label) >> '=' >> make_member_parser(member));
                          };
                      }
                  
                      using detail::rule;
                      using detail::propagate;
                      using detail::property;
                  
                      auto name       = rule("name", "Layer" >> quoted [propagate(&LayerInfo::layerName)]);
                  
                      auto number     = property("number", &LayerInfo::layerNumber);
                      auto color      = property("color", &LayerInfo::color);
                      auto visible    = property("visible", &LayerInfo::visible);
                  
                      auto layer_info = name >> '{' >> +(number | color | visible) >> '}';
                  
                      auto grammar    = rule("layer_info", layer_info);
                  }
                  
                  std::ostream& operator<<(std::ostream& os, LayerInfo const& li) {
                      return os << "LayerInfo "" << li.layerName << ""{"
                          << "number="  << li.layerNumber   << " "
                          << "color="   << li.color         << " "
                          << "visible=" << std::boolalpha << li.visible 
                          << "}
                  ";
                  }
                  
                  int main() {
                      std::string const sample = R"(Layer "L1" {
                      number = 23
                      color = green
                      visible = true
                  })";
                  
                      LayerInfo v;
                      auto f = sample.begin(), l = sample.end();
                      bool ok = parse(f, l, Parser::grammar, v);
                  
                  
                      if (ok)
                          std::cout << "Parsed: " << v << "
                  ";
                      else
                          std::cout << "Parse failed
                  ";
                  
                      if (f!=l)
                          std::cout << "Remaining unparsed: '" << std::string(f,l) << "'
                  ";
                  }
                  

                  印刷品

                  Parsed: LayerInfo "L1"{number=23 color=green visible=true}
                  

                  机智调试信息:生活在 Coliru

                  <layer_info>
                    <try>Layer "L1" {
                      num</try>
                    <name>
                      <try>Layer "L1" {
                      num</try>
                      <quoted>
                        <try> "L1" {
                      number =</try>
                        <success> {
                      number = 23
                   </success>
                        <attributes>[L, 1]</attributes>
                      </quoted>
                      <success> {
                      number = 23
                   </success>
                      <attributes>LayerInfo "L1"{number=0 color= visible=false}
                  </attributes>
                    </name>
                    <number>
                      <try>
                      number = 23
                     </try>
                      <success>
                      color = green
                   </success>
                      <attributes>LayerInfo "L1"{number=23 color= visible=false}
                  </attributes>
                    </number>
                    <number>
                      <try>
                      color = green
                   </try>
                      <fail/>
                    </number>
                    <color>
                      <try>
                      color = green
                   </try>
                      <success>
                      visible = true
                  </success>
                      <attributes>LayerInfo "L1"{number=23 color=green visible=false}
                  </attributes>
                    </color>
                    <number>
                      <try>
                      visible = true
                  </try>
                      <fail/>
                    </number>
                    <color>
                      <try>
                      visible = true
                  </try>
                      <fail/>
                    </color>
                    <visible>
                      <try>
                      visible = true
                  </try>
                      <success>
                  }</success>
                      <attributes>LayerInfo "L1"{number=23 color=green visible=true}
                  </attributes>
                    </visible>
                    <number>
                      <try>
                  }</try>
                      <fail/>
                    </number>
                    <color>
                      <try>
                  }</try>
                      <fail/>
                    </color>
                    <visible>
                      <try>
                  }</try>
                      <fail/>
                    </visible>
                    <success></success>
                    <attributes>LayerInfo "L1"{number=23 color=green visible=true}
                  </attributes>
                  </layer_info>
                  

                  这篇关于Boost Spirit x3:解析为结构体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  <small id='lSVUg'></small><noframes id='lSVUg'>

                      • <bdo id='lSVUg'></bdo><ul id='lSVUg'></ul>

                      • <tfoot id='lSVUg'></tfoot>

                        • <legend id='lSVUg'><style id='lSVUg'><dir id='lSVUg'><q id='lSVUg'></q></dir></style></legend>
                            <tbody id='lSVUg'></tbody>
                          <i id='lSVUg'><tr id='lSVUg'><dt id='lSVUg'><q id='lSVUg'><span id='lSVUg'><b id='lSVUg'><form id='lSVUg'><ins id='lSVUg'></ins><ul id='lSVUg'></ul><sub id='lSVUg'></sub></form><legend id='lSVUg'></legend><bdo id='lSVUg'><pre id='lSVUg'><center id='lSVUg'></center></pre></bdo></b><th id='lSVUg'></th></span></q></dt></tr></i><div id='lSVUg'><tfoot id='lSVUg'></tfoot><dl id='lSVUg'><fieldset id='lSVUg'></fieldset></dl></div>