2

I am trying to parse real numbers using real_parser and the following ureal_policies:

template <typename T>
struct number_real_policies : qi::ureal_policies<T>
{
    static bool const expect_dot = true;

    template <typename Iterator, typename Attribute>
    static bool
    parse_nan(Iterator& first, Iterator const& last, Attribute& attr) {
        return false;
    }

    template <typename Iterator, typename Attribute>
    static bool
    parse_inf(Iterator& first, Iterator const& last, Attribute& attr) {
        return false;
    }
};

It seems to perfectly parse all variations of the real number format I need but I noticed that the following string is accepted as well: ".12345.e12".

Is it normal that two dots are accepted in the fractional part (it only works with the second dot before E/e, and E/e has to be present)?

Thanks in advance

sehe
  • 374,641
  • 47
  • 450
  • 633

1 Answers1

1

As @llonesmiz correctly pointed out in my test application, it works exactly as designed:

Live On Coliru

It looks like you forget to check the parser exit code?

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi    = boost::spirit::qi;
namespace karma = boost::spirit::karma;

typedef std::vector<double> attr_t;

template <typename T>
struct number_real_policies : qi::ureal_policies<T>
{
    static bool const expect_dot = true;

    template <typename Iterator, typename Attribute>
    static bool
    parse_nan(Iterator& first, Iterator const& last, Attribute& attr) {
        return false;
    }

    template <typename Iterator, typename Attribute>
    static bool
    parse_inf(Iterator& first, Iterator const& last, Attribute& attr) {
        return false;
    }
};

template <typename It, typename Skipper = qi::space_type>
    struct parser : qi::grammar<It, attr_t(), Skipper>
{
    parser() : parser::base_type(start)
    {
        using namespace qi;

        start %= *mydouble_;
        BOOST_SPIRIT_DEBUG_NODE(start);
    }

  private:
    qi::rule<It, attr_t(), Skipper> start;
    qi::real_parser<double, number_real_policies<double> > mydouble_;
};

bool doParse(const std::string& input)
{
    typedef std::string::const_iterator It;
    auto f(begin(input)), l(end(input));

    parser<It, qi::space_type> p;
    attr_t data;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,qi::space,data);
        if (ok)   
        {
            std::cout << "parse success\n";
            std::cout << "data: " << 
                karma::format_delimited(karma::columns(3) [*karma::auto_], ' ', data) << "\n";
        }
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<It>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

int main()
{

    bool ok = doParse(
            "0.    2.    .3    \n  "
            "0.e7  2.e7  .3e7  \n"
            "0.e-7 2.e-7 .3e-7 \n"
            // shouldn't accept:
            //"0..e7\n"
            "0.3.e7\n"
            );
    return ok? 0 : 255;
}

Output:

parse success
data: 0.0 2.0 0.3 
0.0 2.0e07 3.0e06 
0.0 2.0e-07 3.0e-08 
0.3 

trailing unparsed: '.e7
'
sehe
  • 374,641
  • 47
  • 450
  • 633
  • It also works with ureal_policies. It just has unparsed text at the end. –  Mar 07 '13 at 07:49
  • [This](http://liveworkspace.org/code/1uSkAG$0) seems to work, and it's also 1.53. –  Mar 07 '13 at 07:52
  • I believe it's a case of just checking the return of qi::parse. Same as [this](http://stackoverflow.com/questions/12864978/boost-spirit-signals-successful-parsing-despite-token-being-incomplete/12868247#12868247). –  Mar 07 '13 at 07:54
  • Mmm. Good call. I think I'm gonna retire. I'm getting blind. – sehe Mar 07 '13 at 08:23
  • Lesson for the day: If you make karma output to look exactly like the input, you might become blind to the difference between error output and success output. Or something silly like that. Thanks for the help, @llonesmiz – sehe Mar 07 '13 at 08:33
  • @llonesmiz Sigh. I had just found that rock to hide under ... :) – sehe Mar 07 '13 at 08:39
  • Thanks a lot, this was it. I actually had another rule that did accept the ".e12" at the end.. I am in the process of writing unit tests for an entire grammar. Does anyone know a good way of testing each rule independently of the others? –  Mar 07 '13 at 15:30
  • 1
    @dferer I personally scrutinize the output of with #define BOOST_SPIRIT_DEBUG (see code) whenever anything unexpected happens. In time, you learn to expect the right things :) – sehe Mar 07 '13 at 15:58
  • @sehe ok, i'll do that. Thanks for your help –  Mar 07 '13 at 17:16