Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
346 views
in Technique[技术] by (71.8m points)

c++ - boost spirit qi numeric parsing of integer and floating points

i am trying to make sense of the following result. The test case code is

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/phoenix.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>

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

namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;

using phoenix::at_c;
using phoenix::push_back;
using phoenix::bind;

template <typename P>
void test_parser(
    char const* input, P const& p, bool full_match = true)
{
    using boost::spirit::qi::parse;

    char const* f(input);
    char const* l(f + strlen(f));
    if (parse(f, l, p) && (!full_match || (f == l)))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}


int main() {

test_parser("+12345", qi::int_ ); //Ok
test_parser("+12345", qi::double_ - qi::int_ ); //failed, as expected
test_parser("+12345.34", qi::int_ );  // failed, as expected
test_parser("+12345.34", qi::double_ - qi::int_ );  //failed but it should be Ok!
};

the motivation here is that i want to match numbers '12345' as integers and NEVER as floating points. '12345.34' will match double_ and never int_ but the reciprocal case is not true; '12345' matches both integers (int_ ) and floating point (double_ ). I tried double_ - int_ and it successfully failed to match '12345'. However my hope was that the last test case '12345.34' would positively match double_ - int_, but the result i get is fail to match.

Why this is so, and how do i get a parser that only matches integers and another that only matches floating points (like in c, 5.0 would be interpreted as floating point)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For your specific example, I think it's actually described in the Boost Spirit documentation under RealPolicies Specialization. To make things a bit easier for you, I whipped out a quick "real" parser, that only parses real numbers and not integers(or at least it worked with your simplified examples):

template <typename T>
struct strict_real_policies : qi::real_policies<T>
{
    static bool const expect_dot = true;
};

qi::real_parser< double, strict_real_policies<double> > real;

And you can use this just like any other parser(like int_ and double_). You might have to add:

#include <boost/spirit/include/qi_numeric.hpp>

To get it to compile.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...