...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The real_parser
can parse
real numbers of arbitrary length and size limited by its template parameter,
T
. The numeric base type
T
can be a user defined
numeric type such as fixed_point (fixed point reals) and bignum (unlimited
precision numbers) as long as the type follows certain expression requirements
(documented below).
// forwards to <boost/spirit/home/qi/numeric/real.hpp> #include <boost/spirit/include/qi_real.hpp>
Also, see Include Structure.
Name |
---|
|
|
|
|
Note | |
---|---|
|
template <typename T, typename RealPolicies> struct real_parser;
Parameter |
Description |
Default |
---|---|---|
|
The numeric base type of the numeric parser. |
none |
|
Policies control the parser's behavior. |
|
Notation
n
An object of T
,
the numeric base type.
num
Numeric literal, any real value, or a Lazy Argument that evaluates to a real value.
RP
A RealPolicies
(type).
exp
A int
exponent.
b
A bool
flag.
f
, l
ForwardIterator
. first/last
iterator pair.
Semantics of an expression is defined only where it differs from, or
is not defined in PrimitiveParser
.
Expression |
Semantics |
---|---|
float_ double_ long_double
|
Parse a real using the default policies ( |
lit(num) float_(num) double_(num) long_double(num)
|
Match the literal |
real_parser< T, RealPolicies >()
|
Parse a real of type |
real_parser< T, RealPolicies >()(num)
|
Match the literal |
Expression |
Attribute |
---|---|
lit(num)
|
|
float_ float_(num)
|
|
double_ double_(num)
|
|
long_double long_double(num)
|
|
real_parser< T, RealPolicies >() real_parser< T, RealPolicies >()(num)
|
|
O(N), where N is the number of characters (including the digits, exponent, sign, etc.) being parsed.
T
The numeric base type, T
,
the minimum expression requirements listed below must be valid. Take
note that additional requirements may be imposed by custom policies.
Expression |
Semantics |
---|---|
|
Default construct. |
|
Construct from an |
|
Addition. |
|
Subtraction. |
|
Multiplication. |
|
|
|
Maximum Digits for |
|
Maximum Digits for |
|
Maximum value for |
|
Minimum value for |
|
Multiply |
|
Negate |
|
Return |
Note | |
---|---|
The additional spirit real number traits above are provided to allow custom implementations to implement efficient real number parsers. For example, for certain custom real numbers, scaling to a base 10 exponent is a very cheap operation. |
RealPolicies
The RealPolicies
template
parameter is a class that groups all the policies that control the parser's
behavior. Policies control the real number parsers' behavior.
The default is real_policies<T>
. The default is provided to take
care of the most common case (there are many ways to represent, and hence
parse, real numbers). In most cases, the default policies are sufficient
and can be used straight out of the box. They are designed to parse C/C++
style floating point numbers of the form nnn.fff.Eeee
where nnn
is the whole
number part, fff
is the
fractional part, E
is
'e'
or 'E'
and eee
is the exponent
optionally preceded by '-'
or '+'
with the additional
detection of NaN and Inf as mandated by the C99 Standard and proposed
for inclusion into the C++0x Standard: nan, nan(...), inf and infinity
(the matching is case-insensitive). This corresponds to the following
grammar:
sign = lit('+') | '-' ; nan = -lit("1.0#") >> no_case["nan"] >> -('(' >> *(char_ - ')') >> ')') ; inf = no_case[lit("inf") >> -lit("inity")] ; floating_literal = -sign >> ( nan | inf | fractional_constant >> -exponent_part | +digit >> exponent_part ) ; fractional_constant = *digit >> '.' >> +digit | +digit >> -lit('.') ; exponent_part = (lit('e') | 'E') >> -sign >> +digit ;
There are four RealPolicies
predefined for immediate use:
Table 4. Predefined Policies
Policies |
Description |
---|---|
|
Without sign. |
|
With sign. |
|
Without sign, dot required. |
|
With sign, dot required. |
Note | |
---|---|
Integers are considered a subset of real numbers, so for instance,
|
RealPolicies
Expression Requirements
For models of RealPolicies
the following expressions must be valid:
Expression |
Semantics |
---|---|
|
Allow leading dot. |
|
Allow trailing dot. |
|
Require a dot. |
|
Parse the prefix sign (e.g. '-'). Return |
|
Parse the integer at the left of the decimal point. Return
|
|
Parse the decimal point. Return |
|
Parse the fraction after the decimal point. Return |
|
Parse the exponent prefix (e.g. 'e'). Return |
|
Parse the actual exponent. Return |
|
Parse a NaN. Return |
|
Parse an Inf. Return |
The parse_nan
and parse_inf
functions get called whenever:
a number to parse does not start with a digit (after having successfully parsed an optional sign)
or
after a real number of the value 1 (having no exponential part and a fractional part value of 0) has been parsed.
The first call recognizes representations of NaN or Inf starting with
a non-digit character (such as NaN, Inf, QNaN etc.). The second call
recognizes representation formats starting with a 1.0
(such as "1.0#NAN"
or "1.0#INF"
etc.).
The functions should return true if a Nan or Inf has been found. In this
case the attribute n
should be set to the matched value (NaN or Inf). The optional sign will
be automatically applied afterwards.
RealPolicies
Specializations
The easiest way to implement a proper real parsing policy is to derive
a new type from the type real_policies
while overriding the aspects of the parsing which need to be changed.
For example, here's the implementation of the predefined strict_real_policies
:
template <typename T> struct strict_real_policies : real_policies<T> { static bool const expect_dot = true; };
Note | |
---|---|
The test harness for the example(s) below is presented in the Basics Examples section. |
Some using declarations:
using boost::phoenix::val; using boost::spirit::qi::double_; using boost::spirit::qi::real_parser; using boost::spirit::qi::lit;
Basic real number parsing:
// double test_parser("+12345e6", double_); test_parser("-12345e6", double_); test_parser("+12345e6", double_(12345e6)); test_parser("-12345e6", double_(-123456e6)); test_parser("+12345e6", double_(val(12345e6))); test_parser("-12345e6", double_(val(-123456e6))); // literals test_parser("+12345e6", lit(12345e6)); test_parser("-12345e6", lit(-123456e6)); test_parser("+12345e6", lit(val(12345e6))); test_parser("-12345e6", lit(val(-123456e6)));
A custom real number policy:
/////////////////////////////////////////////////////////////////////////////// // These policies can be used to parse thousand separated // numbers with at most 2 decimal digits after the decimal // point. e.g. 123,456,789.01 /////////////////////////////////////////////////////////////////////////////// template <typename T> struct ts_real_policies : boost::spirit::qi::ureal_policies<T> { // 2 decimal places Max template <typename Iterator, typename Attribute> static bool parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr) { return boost::spirit::qi:: extract_uint<T, 10, 1, 2, true>::call(first, last, attr); } // No exponent template <typename Iterator> static bool parse_exp(Iterator&, Iterator const&) { return false; } // No exponent template <typename Iterator, typename Attribute> static bool parse_exp_n(Iterator&, Iterator const&, Attribute&) { return false; } // Thousands separated numbers template <typename Iterator, typename Attribute> static bool parse_n(Iterator& first, Iterator const& last, Attribute& attr) { using boost::spirit::qi::uint_parser; namespace qi = boost::spirit::qi; uint_parser<unsigned, 10, 1, 3> uint3; uint_parser<unsigned, 10, 3, 3> uint3_3; T result = 0; if (parse(first, last, uint3, result)) { bool hit = false; T n; Iterator save = first; while (qi::parse(first, last, ',') && qi::parse(first, last, uint3_3, n)) { result = result * 1000 + n; save = first; hit = true; } first = save; if (hit) attr = result; return hit; } return false; } };
And its use:
real_parser<double, ts_real_policies<double> > ts_real; test_parser("123,456,789.01", ts_real); test_parser("123,456,789.01", ts_real(123456789.01));