我只是在Spirit Code Base中改编了一个示例解析器,并测试了它的工作原理。代码如下,
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
#include <boost/spirit/home/classic/core/parser.hpp>
//#include <boost/spirit/include/qi.hpp> //UNCOMMENT THIS!
#include <iostream>
#include <string>
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
using namespace std;
using namespace BOOST_SPIRIT_CLASSIC_NS;
//namespace qi = boost::spirit::qi; //UNCOMMENT THIS!
template <typename T, int DecimalPlaces=4>
struct fixed_point_parser : boost::spirit::classic::parser<fixed_point_parser<T>>
{
static constexpr int pow10[10] = {
1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000
};
typedef fixed_point_parser<T> self_t;
template <typename ScannerT>
struct result
{
typedef typename match_result<ScannerT, uint64_t>::type type;
};
fixed_point_parser() {} //ctor
template <typename ScannerT>
typename parser_result<self_t, ScannerT>::type
parse(ScannerT const& scan) const
{
typedef typename parser_result<fixed_point_parser, ScannerT>::type RT;
if (!scan.at_end())
{
uint_parser<int, 10, 1, 6> int_part;
typename ScannerT::iterator_t save = scan.first;
RT n_match = int_part.parse(scan);
T n = n_match.has_valid_attribute() ?
n_match.value() : T(0);
bool got_a_number = n_match;
if (got_a_number)
{
n *= pow10[DecimalPlaces];
if (ch_p(".").parse(scan))
{
RT frac = int_part.parse(scan);
if (frac)
{
n += frac.value() * pow10[DecimalPlaces - frac.length()];
return scan.create_match(n_match.length() + frac.length() + 1, n, save, scan.first);
}
else
return scan.no_match();
}
return scan.create_match(n_match.length(), n, save, scan.first);
}
}
return scan.no_match();
}
};
int main()
{
string str = "1234.5";
fixed_point_parser<uint64_t> f{};
// if (qi::parse(str.begin(), str.end(), f)) //UNCOMMENT THIS!
if (parse(str.begin(), str.end(), f).full) //COMMENT THIS OUT!
{
cout << "Parsing succeeded\n";
}
else
{
cout << "Parsing failed\n";
}
return 0;
}
代码将正确编译和解析。
但是一旦您取消注释“取消注释!”并尝试使其与qi配合使用,然后编译将失败。
有人可以帮忙解释原因吗?
答案 0 :(得分:1)
好吧,我真的想出了办法。
template <typename T, int DecimalPlaces=4 >
struct fixed_point_parser
: primitive_parser<fixed_point_parser<T> >
{
static constexpr int pow10[10] = {
1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000
};
template <typename Context, typename Iterator>
struct attribute
{
typedef T type;
};
template <typename Iterator, typename Context, typename Skipper>
bool parse(Iterator& first, Iterator const& last
, Context& /*context*/, Skipper const& skipper
, T& attr_) const
{
bool got_a_number = extract_uint<T, 10, 1, -1>::call(first, last, attr_);
if (got_a_number)
{
attr_ *= pow10[DecimalPlaces];
if (ureal_policies<T>::parse_dot(first, last))
{
T frac_part;
Iterator save = first;
bool got_frac_part = extract_uint<T, 10, 1, -1>::call(first, last, frac_part);
if (got_frac_part)
{
auto dist = first - save;
attr_ += frac_part * pow10[DecimalPlaces - dist];
}
}
return true;
}
return false;
}
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper
, Attribute& attr_param) const
{
// this case is called when Attribute is not T
T attr_;
if (parse(first, last, context, skipper, attr_))
{
boost::spirit::traits::assign_to(attr_, attr_param);
return true;
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("fixed_point");
}
};