解析浮点数,后跟包含“ e”字符的字符串

时间:2019-02-01 18:37:52

标签: c++ boost c++17 boost-spirit boost-spirit-x3

我正在尝试解析这种类型的字符串

1.2e3ex
1.2e3 ex

并设置好

x3::float_ >> "ex"

不幸的是,这无法解析

1ex

完整的示例代码:

#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

const auto parser = x3::float_ >> "em";

int main()
{
  std::string input = "1em";
  auto first = input.begin();
  auto last = input.end();

  float value{};
  bool result = x3::phrase_parse(first, last, parser, x3::blank, value);

  if(result)
  {
    if(first == last)
      std::cout << "parse succesful: " << value << '\n';
    else
      std::cout << "incomplete parse: " << value << '\n';
  }
  else
    std::cout << "parse unsuccesful\n";
}

还有live on Coliru

似乎我需要跳过一些箍,

struct non_scientific_float_policy : x3::real_policies<float>
{
  template <typename Iterator>
  static bool parse_exp(Iterator& first, Iterator const& last)
  {
    return false;
  }
};

const auto non_scientific_float = x3::real_parser<float, non_scientific_float_policy>{};

provide an alternative

const auto parser = non_scientific_float >> "em" | x3::float_ >> "em";

还有别的办法吗?

2 个答案:

答案 0 :(得分:4)

您可以通过调整实际策略parse_exp来解决此问题,以使指数检测不仅需要[eE]字符,而且还需要[eE][-+]?[0-9]

#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

template <typename T>
struct alt_real_policies : x3::real_policies<T>
{
    template <typename Iterator>
    static bool parse_exp(Iterator& first, Iterator const& last)
    {
        Iterator save = first;
        if (x3::real_policies<T>::parse_exp(first, last)) {
            Iterator iter = first;
            if (x3::extract_int<x3::unused_type, 10, 1, 1>::call(iter, last, x3::unused))
                return true;
        }
        first = save;
        return false;
    }

};

const x3::real_parser<float, alt_real_policies<float>> altfloat;
const auto parser = altfloat >> "em";

int main()
{
    std::string input = "1em";
    auto first = input.begin();
    auto last = input.end();

    float value{};
    bool result = x3::phrase_parse(first, last, parser, x3::blank, value);

    if (result)
    {
        if (first == last)
            std::cout << "parse succesful: " << value << '\n';
        else
            std::cout << "incomplete parse: " << value << '\n';
    }
    else
        std::cout << "parse unsuccesful\n";
}

http://coliru.stacked-crooked.com/a/f60f334c960cb602

答案 1 :(得分:0)

您可以将替代策略用于指数的非贪婪解析。我能想到的最简单的是:

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;

template <typename T>
struct no_exponent : x3::real_policies<T> {
    template <typename It>
        static bool parse_exp(It, It) { return false; }
};

x3::real_parser<double, no_exponent<double> > noexp_;

const auto parser = (x3::float_ | noexp_) >> "em";

int main() {
    std::string input = "-1.67em";
    auto first = input.begin();
    auto last = input.end();

    float value{};
    bool result = x3::phrase_parse(first, last, parser, x3::blank, value);

    if (result) {
        if (first == last)
            std::cout << "parse succesful: " << value << '\n';
        else
            std::cout << "incomplete parse: " << value << '\n';
    } else
    {
        std::cout << "parse unsuccesful\n";
    }
}

打印:

parse succesful: -1.67