1. <legend id='l0ZmQ'><style id='l0ZmQ'><dir id='l0ZmQ'><q id='l0ZmQ'></q></dir></style></legend><tfoot id='l0ZmQ'></tfoot>
      • <bdo id='l0ZmQ'></bdo><ul id='l0ZmQ'></ul>

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

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

        理解 Boost.Spirit 中的列表运算符 (%)

        时间:2023-07-19

          1. <small id='VX1JH'></small><noframes id='VX1JH'>

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

                  <tfoot id='VX1JH'></tfoot>

                • 本文介绍了理解 Boost.Spirit 中的列表运算符 (%)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  你能帮我理解 a % b 解析器和它扩展的 a >> 之间的区别吗?*(b >> a) 形式在 Boost.Spirit 中?即使参考手册 表示它们是等价的,

                  Can you help me understand the difference between the a % b parser and its expanded a >> *(b >> a) form in Boost.Spirit? Even though the reference manual states that they are equivalent,

                  列表运算符 a % b 是一种二元运算符,它匹配由 ba 的一个或多个重复的列表代码>.这相当于 a >>*(b >> a).

                  The list operator, a % b, is a binary operator that matches a list of one or more repetitions of a separated by occurrences of b. This is equivalent to a >> *(b >> a).

                  以下程序会根据使用的程序产生不同的结果:

                  the following program produces different results depending on which is used:

                  #include <iostream>
                  #include <string>
                  #include <vector>
                  
                  #include <boost/fusion/include/adapt_struct.hpp>
                  #include <boost/spirit/include/qi.hpp>
                  
                  struct Record {
                    int id;
                    std::vector<int> values;
                  };
                  
                  BOOST_FUSION_ADAPT_STRUCT(Record,
                    (int, id)
                    (std::vector<int>, values)
                  )
                  
                  int main() {
                    namespace qi = boost::spirit::qi;
                  
                    const auto str = std::string{"1: 2, 3, 4"};
                  
                    const auto rule1 = qi::int_ >> ':' >> (qi::int_ % ',')                 >> qi::eoi;
                    const auto rule2 = qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_)) >> qi::eoi;
                  
                    Record record1;
                    if (qi::phrase_parse(str.begin(), str.end(), rule1, qi::space, record1)) {
                      std::cout << record1.id << ": ";
                      for (const auto& value : record1.values) { std::cout << value << ", "; }
                      std::cout << '
                  ';
                    } else {
                      std::cerr << "syntax error
                  ";
                    }
                  
                    Record record2;
                    if (qi::phrase_parse(str.begin(), str.end(), rule2, qi::space, record2)) {
                      std::cout << record2.id << ": ";
                      for (const auto& value : record2.values) { std::cout << value << ", "; }
                      std::cout << '
                  ';
                    } else {
                      std::cerr << "syntax error
                  ";
                    }
                  }
                  

                  在 Coliru 上直播

                  1: 2, 3, 4, 
                  1: 2, 
                  

                  rule1rule2 的不同仅在于 rule1 使用列表运算符 ((qi::int_ % ',')) 和 rule2 使用其扩展形式 ((qi::int_ >> *(',' >> qi::int_))).然而,rule1 产生了 1: 2, 3, 4,(如预期的那样)和 rule2 产生了 1: 2,>.我无法理解 rule2 的结果:1) 为什么它与 rule1 的结果不同和 2) 为什么 34 未包含在 record2.values 中,即使 phrase_parse 以某种方式返回 true?

                  rule1 and rule2 are different only in that rule1 uses the list operator ((qi::int_ % ',')) and rule2 uses its expanded form ((qi::int_ >> *(',' >> qi::int_))). However, rule1 produced 1: 2, 3, 4, (as expected) and rule2 produced 1: 2,. I cannot understand the result of rule2: 1) why is it different from that of rule1 and 2) why were 3 and 4 not included in record2.values even though phrase_parse returned true somehow?

                  推荐答案

                  更新 X3 版本已添加

                  首先,您在这里陷入了一个深陷陷阱:

                  First off, you fallen into a deep trap here:

                  Qi 规则不适用于 auto.使用 qi::copy 或仅使用 qi::rule<>.你的程序有未定义的行为,它确实对我来说崩溃了(valgrind 指出了悬空引用的来源).

                  Qi rules don't work with auto. Use qi::copy or just used qi::rule<>. Your program has undefined behaviour and indeed it crashed for me (valgrind pointed out where the dangling references originated).

                  所以,首先:

                  const auto rule = qi::copy(qi::int_ >> ':' >> (qi::int_ % ',')                 >> qi::eoi); 
                  

                  现在,当你删除程序中的冗余时,你得到:

                  Now, when you delete the redundancy in the program, you get:

                  生活在 Coliru

                  int main() {
                      test(qi::copy(qi::int_ >> ':' >> (qi::int_ % ',')));
                      test(qi::copy(qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_))));
                  }
                  

                  打印

                  1: 2, 3, 4, 
                  1: 2, 
                  

                  原因和解决方法

                  成功解析3, 4发生了什么?

                  好吧,属性传播规则表明qi::int_>>*(',' >> qi::int_) 暴露了一个 tuple;>.为了神奇地 DoTheRightThing(TM) Spirit 不小心将 int 误触发并分配"到属性引用中,而忽略了剩余的 vector.

                  Well, the attribute propagation rules indicate that qi::int_ >> *(',' >> qi::int_) exposes a tuple<int, vector<int> >. In a bid to magically DoTheRightThing(TM) Spirit accidentally misfires and "assigngs" the int into the attribute reference, ignoring the remaining vector<int>.

                  如果要将容器属性解析为原子组",请使用qi::as<>:

                  If you want to make container attributes parse as "an atomic group", use qi::as<>:

                  test(qi::copy(qi::int_ >> ':' >> qi::as<Record::values_t>() [ qi::int_ >> *(',' >> qi::int_)]));
                  

                  这里 as<> 作为属性兼容性启发式的障碍,语法知道你的意思:

                  Here as<> acts as a barrier for the attribute compatibility heuristics and the grammar knows what you meant:

                  生活在 Coliru 上

                  #include <iostream>
                  #include <string>
                  #include <vector>
                  
                  #include <boost/fusion/include/adapt_struct.hpp>
                  #include <boost/spirit/include/qi.hpp>
                  
                  struct Record {
                    int id;
                    using values_t = std::vector<int>;
                    values_t values;
                  };
                  
                  BOOST_FUSION_ADAPT_STRUCT(Record, id, values)
                  
                  namespace qi = boost::spirit::qi;
                  
                  template <typename T>
                  void test(T const& rule) {
                      const std::string str = "1: 2, 3, 4";
                  
                      Record record;
                  
                      if (qi::phrase_parse(str.begin(), str.end(), rule >> qi::eoi, qi::space, record)) {
                          std::cout << record.id << ": ";
                          for (const auto& value : record.values) { std::cout << value << ", "; }
                          std::cout << '
                  ';
                      } else {
                          std::cerr << "syntax error
                  ";
                      }
                  }
                  
                  int main() {
                      test(qi::copy(qi::int_ >> ':' >> (qi::int_ % ',')));
                      test(qi::copy(qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_))));
                      test(qi::copy(qi::int_ >> ':' >> qi::as<Record::values_t>() [ qi::int_ >> *(',' >> qi::int_)]));
                  }
                  

                  印刷品

                  1: 2, 3, 4, 
                  1: 2, 
                  1: 2, 3, 4, 
                  

                  这篇关于理解 Boost.Spirit 中的列表运算符 (%)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                • <legend id='VJZ8p'><style id='VJZ8p'><dir id='VJZ8p'><q id='VJZ8p'></q></dir></style></legend>

                  1. <small id='VJZ8p'></small><noframes id='VJZ8p'>

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

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