如何使用qi :: hold [] Parser指令。 (boost :: swap的属性类型问题)

时间:2015-05-06 09:09:11

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

我有一个解析为boost::variant<int, double, std::string>的解析器

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using namespace std;

typedef map<string,  boost::variant<int, double, string> > namevalue;
typedef pair<string, boost::variant<int, double, string> > namevaluepair;

template <typename Iterator>
struct keys_and_values2
    :   grammar<Iterator, namevalue(), ascii::blank_type>
{
    keys_and_values2()
        :   keys_and_values2::base_type(start)
    {
        start %= query >> qi::eoi;
        query =  +pair;
        value =  qi::int_ | qi::double_ | qi::lexeme[+(qi::char_ - qi::eol)] ;
        pair  =  key >> qi::lit(':') >> value >> qi::eol;
        key   =  qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
    }
    qi::rule<Iterator, namevalue(), ascii::blank_type> start;
    qi::rule<Iterator, namevalue(), ascii::blank_type> query;
    qi::rule<Iterator, namevaluepair(), ascii::blank_type> pair;
    qi::rule<Iterator, std::string(), ascii::blank_type> key;
    qi::rule<Iterator, boost::variant<int, double, string>(), ascii::blank_type> value;
};

解析输入在这里:

Sarai    :    52.731199473801
Jamiya   :    Jelly Drop
Clara    :    -92.408605869885
Janelle  :    132349223
Briley   :    -40.905352495602

第一行“Sarai”失败了。如果我像这样反转解析double和int:

value =  qi::double_ | qi::int_ | qi::lexeme[+(qi::char_ - qi::eol)] ;

它工作正常,但“Janelle”的整数值被解析为double。在BOOST FAQBOOST documentation之后,我想像这样使用qi :: hold []:

value =  qi::hold[qi::int_] | qi::hold[qi::double_] | qi::lexeme[+(qi::char_ - qi::eol)] ;

但是有了这个,我收到一条关于缺失功能的消息:swap()。这实际上记录在boost docs(注释)中。但解释是非常简洁。我无法找到此交换函数的正确属性类型。有人可以帮忙吗?

编译器消息:

E:\Boost\boost_1_58_0\boost/spirit/home/support/attributes.hpp(1036) : error C2784: 'void boost::spirit::swap(boost::spirit::multi_pass<T,Policies> &,boost::spirit::multi_pass<T,Policies> &)' : could not deduce template argument for 'boost::spirit::multi_pass<T,Policies> &' from 'int' 

<小时/> 的更新
answer of sehe适用于上述数据。但是,如果我将输入更改为以下内容:

Sarai    :    52.731199473801
Jamiya   :    Jelly Drop
Clara    :    -92.408605869885
Rebekah  :    240ad9beb53bbfafcd5
Janelle  :    132349223
Cloe     :    456ABCabvc
Briley   :    -40.905352495602

我对“Rebekah”值有疑问。我还看到评估值的顺序很重要。这一次,问题不再是double值,而是在intstring之间。我想实现这样的事情:(政策?)

  1. 只有数字,可选减号且包含点的所有内容都是double
  2. 只有数字和可选减号的所有内容均为int
  3. 其他一切都是std::string
  4. <小时/> 的解决方案
    有时,理解问题比解决问题更重要。

    问题不在于解析器策略,而是我对解析规则的定义(见上文)。规则3“其他一切”实际上包括:“一切都符合EOL”。因此,value规则中的所有三个备选方案必须与此匹配:

    value =   strict_double >> qi::eol
            | qi::int_ >> qi::eol
            | qi::lexeme[+(qi::char_ - qi::eol)] >> qi::eol;
    

    通过此更改,sehe's answer就像魅力一样!

1 个答案:

答案 0 :(得分:1)

Hold不用于此。

想一想:它会有什么帮助?它不会使整数分支不匹配,因此它仍然无法解析,hold不会还原任何东西。

hold[]主要用于容器属性¹,其中部分解析可以修改属性。容器通常已经实现了交换。你在这里咆哮错误的树

  

¹包括字符串,参见例如
Understanding Boost.spirit's string parser   
boost::spirit::qi duplicate parsing on the output   
Boost spirit revert parsing   
Boost Spirit optional parser and backtracking

解决问题:

您可以使用严格实际策略仅将实际值解析为double。

value =  strict_double | qi::int_ | qi::lexeme[+(qi::char_ - qi::eol)] ;

// with
qi::real_parser<double, qi::strict_real_policies<double> > strict_double;

有关单元测试的信息,请参阅Parse int or double using boost spirit (longest_d)

<强> Live On Coliru

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

namespace qi    = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

typedef boost::variant<int, double, std::string> value_t;
typedef std::map<std::string, value_t> namevalue;
typedef std::pair<std::string, value_t> namevaluepair;

template <typename Iterator>
struct keys_and_values2
    :   qi::grammar<Iterator, namevalue(), ascii::blank_type>
{
    keys_and_values2() : keys_and_values2::base_type(start)
    {
        start %= query >> qi::eoi;
        query =  +pair;
        value =  strict_double | qi::int_ | qi::lexeme[+(qi::char_ - qi::eol)] ;
        pair  =  key >> qi::lit(':') >> value >> qi::eol;
        key   =  qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");

        BOOST_SPIRIT_DEBUG_NODES((start)(query)(value)(pair)(key))
    }
  private:
    qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
    qi::rule<Iterator, namevalue(),     ascii::blank_type> start;
    qi::rule<Iterator, namevalue(),     ascii::blank_type> query;
    qi::rule<Iterator, namevaluepair(), ascii::blank_type> pair;
    qi::rule<Iterator, std::string(),   ascii::blank_type> key;
    qi::rule<Iterator, value_t(),       ascii::blank_type> value;
};

int main() {
    typedef boost::spirit::istream_iterator It;
    It f(std::cin >> std::noskipws), l;

    keys_and_values2<It> g;
    namevalue data;
    bool ok = qi::phrase_parse(f,l,g,ascii::blank,data);

    if (ok) {
        std::cout << "Parse succeeded:\n";
        for(auto& p : data)
            std::cout << "\t'" << p.first << "'\t-> " << p.second << "\n";
    } else
        std::cout << "Parse failed\n";

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

打印

Parse succeeded:
    'Briley'    -> -40.9054
    'Clara' -> -92.4086
    'Jamiya'    -> Jelly Drop
    'Janelle'   -> 132349223
    'Sarai' -> 52.7312

调试信息(如果启用)

<start>
<try>Sarai    :    52.731</try>
<query>
    <try>Sarai    :    52.731</try>
    <pair>
    <try>Sarai    :    52.731</try>
    <key>
        <try>Sarai    :    52.731</try>
        <success>:    52.731199473801</success>
        <attributes>[[S, a, r, a, i]]</attributes>
    </key>
    <value>
        <try>    52.731199473801\n</try>
        <success>\nJamiya   :    Jelly</success>
        <attributes>[52.7312]</attributes>
    </value>
    <success>Jamiya   :    Jelly </success>
    <attributes>[[[S, a, r, a, i], 52.7312]]</attributes>
    </pair>
    <pair>
    <try>Jamiya   :    Jelly </try>
    <key>
        <try>Jamiya   :    Jelly </try>
        <success>:    Jelly Drop\nClar</success>
        <attributes>[[J, a, m, i, y, a]]</attributes>
    </key>
    <value>
        <try>    Jelly Drop\nClara</try>
        <success>\nClara    :    -92.4</success>
        <attributes>[[J, e, l, l, y,  , D, r, o, p]]</attributes>
    </value>
    <success>Clara    :    -92.40</success>
    <attributes>[[[J, a, m, i, y, a], [J, e, l, l, y,  , D, r, o, p]]]</attributes>
    </pair>
    <pair>
    <try>Clara    :    -92.40</try>
    <key>
        <try>Clara    :    -92.40</try>
        <success>:    -92.40860586988</success>
        <attributes>[[C, l, a, r, a]]</attributes>
    </key>
    <value>
        <try>    -92.408605869885</try>
        <success>\nJanelle  :    13234</success>
        <attributes>[-92.4086]</attributes>
    </value>
    <success>Janelle  :    132349</success>
    <attributes>[[[C, l, a, r, a], -92.4086]]</attributes>
    </pair>
    <pair>
    <try>Janelle  :    132349</try>
    <key>
        <try>Janelle  :    132349</try>
        <success>:    132349223\nBrile</success>
        <attributes>[[J, a, n, e, l, l, e]]</attributes>
    </key>
    <value>
        <try>    132349223\nBriley</try>
        <success>\nBriley   :    -40.9</success>
        <attributes>[132349223]</attributes>
    </value>
    <success>Briley   :    -40.90</success>
    <attributes>[[[J, a, n, e, l, l, e], 132349223]]</attributes>
    </pair>
    <pair>
    <try>Briley   :    -40.90</try>
    <key>
        <try>Briley   :    -40.90</try>
        <success>:    -40.90535249560</success>
        <attributes>[[B, r, i, l, e, y]]</attributes>
    </key>
    <value>
        <try>    -40.905352495602</try>
        <success>\n</success>
        <attributes>[-40.9054]</attributes>
    </value>
    <success></success>
    <attributes>[[[B, r, i, l, e, y], -40.9054]]</attributes>
    </pair>
    <pair>
    <try></try>
    <key>
        <try></try>
        <fail/>
    </key>
    <fail/>
    </pair>
    <success></success>
    <attributes>[[[[B, r, i, l, e, y], -40.9054], [[C, l, a, r, a], -92.4086], [[J, a, m, i, y, a], [J, e, l, l, y,  , D, r, o, p]], [[J, a, n, e, l, l, e], 132349223], [[S, a, r, a, i], 52.7312]]]</attributes>
</query>
<success></success>
<attributes>[[[[B, r, i, l, e, y], -40.9054], [[C, l, a, r, a], -92.4086], [[J, a, m, i, y, a], [J, e, l, l, y,  , D, r, o, p]], [[J, a, n, e, l, l, e], 132349223], [[S, a, r, a, i], 52.7312]]]</attributes>
</start>