【问题标题】:Is it possible to re-use boost::spirit::qi grammar in another grammar definition?是否可以在另一个语法定义中重用 boost::spirit::qi 语法?
【发布时间】:2012-03-29 12:34:12
【问题描述】:

是否可以在另一个语法中重用boost::spirit:qi 语法(例如作为规则)?

例如,如果我定义一个语法来将文本行解析为包含街道地址的结构。

   template< typename iter >
        struct address_grammar : qi::grammar< iter, address() >
   {
     ...

       qi::rule< iter, std::string() > street_name;
       qi::rule< iter, std::string() > street_number;
       qi::rule< iter, address() > address_;
   }

我可能想在其他两种语法中重用该语法,例如,一种可能用于解析存储在文件中的地址向量。另一种重用可能是更复杂的结构,其中一个字段是这个街道地址结构。

  template< typename iter >
      struct company_grammar : qi::grammar< iter, company() >
  {
     ...
     qi::rule< iter, std::string() > comp_name;
     // can I reuse the address grammar somehow here ???
     qi::rule< iter, company() > company;
  }

我没有在一个地方定义整个语法,而是考虑将其拆分为更小的可重用块,如果它们位于一个头文件中就可以了。我的数据结构稍微复杂一些(结构中的几个字段以及其他结构的列表等等),所以我不想把它放在一个语法中。

这样可以复用boost::spirit::qi语法吗?

编辑:考虑一下,我是否只是在命名空间中定义qi::rules,然后根据我需要的规则组合一个语法?

【问题讨论】:

    标签: c++ boost boost-spirit boost-spirit-qi


    【解决方案1】:

    当然可以。在您的情况下,只需在您的代码中输入address_grammar&lt;iter&gt; address_;。

    让我再举一个例子。 您可以在此处找到可编译的代码: http://ideone.com/GW4jO(另见下文)

    AFAIK,与 qi::grammar 不同,qi::rule 难以重用。


    完整样本

    #include <string>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    
    struct Date {
        int year, month, day;
    };
    struct Time {
        int hour, minute, second;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(
        Date,
        (int, year)
        (int, month)
        (int, day)
    )
    
    BOOST_FUSION_ADAPT_STRUCT(
        Time,
        (int, hour)
        (int, minute)
        (int, second)
    )
    
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    typedef std::string::const_iterator Iterator;
    
    class DateParser:
        public qi::grammar < Iterator, Date() > {
            qi::rule < Iterator, Date() > main;
        public:
            DateParser(): base_type(main) {
                main %= qi::int_ >> '-' >> // Year
                        qi::int_ >> '-' >> // Month
                        qi::int_;          // Day
            }
    };
    
    class TimeParser:
        public qi::grammar < Iterator, Time() > {
            qi::rule < Iterator, Time() > main;
        public:
            TimeParser(): base_type(main) {
                main %= qi::int_ >> ':' >> // Hour
                        qi::int_ >> ':' >> // Minute
                        qi::int_;          // Second
            }
    };
    
    class DateTimeParser:
        public qi::grammar < Iterator, boost::variant<Date, Time>() > {
            qi::rule < Iterator, boost::variant<Date, Time>()> main;
        public:
            DateTimeParser(): base_type(main) {
                main %= date_parser | time_parser;
            }
            DateParser date_parser;
            TimeParser time_parser;
    };
    
    #include<iostream>
    #include<cstdio>
    
    struct Printer : public boost::static_visitor<> {
        void operator()(Date a) const {
            printf("Year: %d, Month: %d, Day: %d\n", a.year, a.month, a.day);
        }
        void operator()(Time a) const {
            printf("Hour: %d, Minute: %d, Second: %d\n", a.hour, a.minute, a.second);
        }
    };
    
    int main() {
        std::string s;
        std::getline(std::cin, s);
        Iterator beg = s.begin(), end = s.end();
        boost::variant<Date, Time> ret;
        phrase_parse(beg, end, DateTimeParser(), ascii::space, ret);
        if (beg != end)
            puts("Parse failed.");
        else
            boost::apply_visitor(Printer(), ret);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多