【问题标题】:Pass a boost::spirit symbol table into a grammar as inherited attribute将 boost::spirit 符号表作为继承属性传递给语法
【发布时间】:2014-10-16 13:58:00
【问题描述】:

我想创建解析键值对列表的语法,但只接受给定的键。如果输入列表包含未知键,则语法应该失败。 “好”键的键可以作为 qi::symbol 表传递给语法。

问题:是否可以将键作为语法的继承属性传递?

我创建了代码原型,但不知道如何将属性信息转换为解析器或语法中的规则或子语法。

#include <iostream>
#include <vector>

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>

using namespace std;
using namespace boost;

namespace qi = boost::spirit::qi;

template <typename I> using string_range = iterator_range<I>;

template <typename I> using pair_type = pair<
  boost::optional<int>,
  boost::optional<string_range<I>>
>;

template <typename I> using pairs_type = vector<pair_type<I>>;

using symbol_table = qi::symbols<char, int>;

template <typename Iterator>
struct keys_and_values
  : qi::grammar<Iterator, pairs_type<Iterator>(symbol_table const&)>
{
  keys_and_values()
    : keys_and_values::base_type(query)
  {
    using namespace qi;
    query =  pair (_r1) >> *((qi::lit(';') | '&') >> pair (_r1));
// How to convert the attribute into the parsing object???
    pair  =  -matches[_r1] >> -('=' >> -value);
    value =  raw[+qi::char_("a-zA-Z_0-9")];
  }
  qi::rule<Iterator, pairs_type<Iterator>(symbol_table const&)> query;
  qi::rule<Iterator, pair_type<Iterator>(symbol_table const&)> pair;
  qi::rule<Iterator, string_range<Iterator>()> value;
};

int main ()
{
  namespace qi = boost::spirit::qi;
  string input { "key1=v1;key2=v2;key3=v3" };

  using string_iterator = string::const_iterator;

  static const keys_and_values <string_iterator> p;
  pairs_type <string_iterator> m;

  symbol_table keys;
  keys.add ("key1", 1) ("key2", 2) ("key3", 3) ;

  string_iterator begin{boost::begin (input)}, end{boost::end(input)};

  if (qi::parse (begin, end, p(boost::phoenix::ref(keys)), m))
    cout << "parse ok\n";
}

link 与线圈上的相同代码。

【问题讨论】:

    标签: c++ parsing boost grammar boost-spirit


    【解决方案1】:

    当然。这与著名的 Nabialek Trick 密切相关。

    而启用机制是qi::lazy:

        pair  =  -matches[lazy(_r1)] >> -('=' >> -value);
    

    我还添加了#define BOOST_SPIRIT_USE_PHOENIX_V3(您可能不必明确设置,具体取决于编译器/增强版本)。

    Live On Coliru

    #define BOOST_SPIRIT_USE_PHOENIX_V3
    #include <iostream>
    #include <vector>
    
    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/include/std_pair.hpp>
    
    using namespace std;
    using namespace boost;
    
    namespace qi = boost::spirit::qi;
    
    template <typename I> using string_range = iterator_range<I>;
    
    template <typename I> using pair_type = pair<
        boost::optional<int>,
        boost::optional<string_range<I>>
    >;
    
    template <typename I> using pairs_type = vector<pair_type<I>>;
    
    using symbol_table = qi::symbols<char, int>;
    
    template <typename Iterator>
    struct keys_and_values
        : qi::grammar<Iterator, pairs_type<Iterator>(symbol_table const&)>
    {
        keys_and_values()
        : keys_and_values::base_type(query)
        {
            using namespace qi;
            query =  pair (_r1) >> *((qi::lit(';') | '&') >> pair (_r1));
            // How to convert the attribute into the parsing object???
            pair  =  -matches[lazy(_r1)] >> -('=' >> -value);
            value =  raw[+qi::char_("a-zA-Z_0-9")];
        }
        qi::rule<Iterator, pairs_type<Iterator>(symbol_table const&)> query;
        qi::rule<Iterator, pair_type<Iterator>(symbol_table const&)> pair;
        qi::rule<Iterator, string_range<Iterator>()> value;
    };
    
    int main ()
    {
        namespace qi = boost::spirit::qi;
        string input { "key1=v1;key2=v2;key3=v3" };
    
        using string_iterator = string::const_iterator;
    
        static const keys_and_values <string_iterator> p;
        pairs_type <string_iterator> m;
    
        symbol_table keys;
        keys.add ("key1", 1) ("key2", 2) ("key3", 3) ;
    
        string_iterator begin{boost::begin (input)}, end{boost::end(input)};
    
        if (qi::parse (begin, end, p(boost::phoenix::ref(keys)), m))
            cout << "parse ok\n";
    }
    

    输出:

    parse ok
    

    【讨论】:

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