Boost::qi: I can't parse signed int8_t into double:
template <typename Iterator>
struct test : qi::grammar<Iterator, double()> {
test() : test::base_type(start) {
number =
parse_number [ _val = _1 ]
parse_number =
qi::int_parser<int8_t>() [ _val = boost::phoenix::static_cast_<double>(_1) ];
start = qi::skip(qi::space)[number];
}
private:
qi::rule<Iterator, double()> start;
qi::rule<Iterator, double()> number;
qi::rule<Iterator, double()> parse_number;
}
I need to parse "255" as int8_t
into number
which is double
. But, as int8_t
, 255 shall be parsed as -1.
Later I wish to expand this to support typename prefixes, so that parse_number
can parse them:
255 : 255
(u8)255 : 255
(s8)255 : -1
Current error messages:
../src/StringTest.cpp:129:106: error: expected ‘{’ before ‘;’ token
129 | parse_prefix = (qi::int_parser<int8_t>()) [ _val = boost::phoenix::static_cast_<double>(_1) ];
| ^
../src/StringTest.cpp:129:28: error: invalid cast to function type ‘boost::spirit::qi::int_parser<signed char>()’
129 | parse_prefix = (qi::int_parser<int8_t>()) [ _val = boost::phoenix::static_cast_<double>(_1) ];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
What is the (correct) way of doing this?
It works for me: Live On Coliru
But you can simplify all the way down to
template <typename It> struct test : qi::grammar<It, double()> {
test() : test::base_type(start) { //
start = qi::int_parser<int8_t>{};
}
private:
qi::rule<It, double()> start;
};
Here's a generalized test-bed: Live On Coliru
To get your type prefixes, I'd consider something like this:
qi::rule<std::string::const_iterator, long double()> parser //
= "(s8)" >> qi::int_parser<int8_t>{}
| "(u8)" >> qi::uint_parser<uint8_t>{}
| "(s16)" >> qi::int_parser<int16_t>{}
| "(u16)" >> qi::uint_parser<uint16_t>{}
| "(s32)" >> qi::int_parser<int32_t>{}
| "(u32)" >> qi::uint_parser<uint32_t>{}
| "(s64)" >> qi::int_parser<int64_t>{}
| "(u64)" >> qi::uint_parser<uint64_t>{}
| "(s128)" >> qi::int_parser<__int128_t>{}
| "(u128)" >> qi::uint_parser<__uint128_t>{}
| "(c)" >> qi::int_parser<char>{}
| qi::real_parser<long double>{};
Note that I switched to
long double
because otherwise large 64-bit integers aren't being represented exactly anymore (double has only 53 bits of significand precision).
Another, pretty exhaustive, test-bed:
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
#include <iostream>
using namespace std::string_literals;
namespace qi = boost::spirit::qi;
void testWithPrefix() {
qi::rule<std::string::const_iterator, long double()> parser //
= "(s8)" >> qi::int_parser<int8_t>{} //
| "(u8)" >> qi::uint_parser<uint8_t>{} //
| "(s16)" >> qi::int_parser<int16_t>{} //
| "(u16)" >> qi::uint_parser<uint16_t>{} //
| "(s32)" >> qi::int_parser<int32_t>{} //
| "(u32)" >> qi::uint_parser<uint32_t>{} //
| "(s64)" >> qi::int_parser<int64_t>{} //
| "(u64)" >> qi::uint_parser<uint64_t>{} //
| "(s128)" >> qi::int_parser<__int128_t>{} //
| "(u128)" >> qi::uint_parser<__uint128_t>{} //
| "(c)" >> qi::int_parser<char>{} //
| qi::real_parser<long double>{};
for (auto prefix : {"(s8)", "(u8)", "(c)", "(i16)", "(u16)", "(s32)", "(u32)", //
"(s64)", "(u64)", "(s128)", "(u128)", ""})
for (auto sign : {""/*, "+"*/, "-"})
for (std::string literal :
{
"0",
"1", // 2^0
"127", // 2^7-1
"128", // 2^7
"255", // 2^8-1
"256", // 2^8
"32767", // 2^15-1
"32768", // 2^15
"65535", // 2^16-1
"65536", // 2^16
"2147483647", // 2^31-1
"2147483648", // 2^31
"4294967295", // 2^32-1
"4294967296", // 2^32
"9223372036854775807", // 2^63-1
"9223372036854775808", // 2^63
"18446744073709551615", // 2^64-1
"18446744073709551616", // 2^64
"170141183460469231731687303715884105727", // 2^127-1
"170141183460469231731687303715884105728", // 2^127
"123e+45",
}) //
{
std::string const input = prefix + (sign + literal);
long double actual, expected = std::strtold((sign + literal).c_str(), nullptr);
if (qi::parse( //
input.begin(), input.end(), //
parser >> qi::eoi, actual)) //
{
std::cout << "Parsed: " << std::setw(43) << quoted(input) << " -> " << actual << "\n";
if (expected != actual)
std::cout << " (mismatch: " << expected << "\n";
} else {
std::cout << " -- (Failing to parse " << quoted(input) << ")\n";
break;
}
}
}
int main() {
std::cout << std::fixed << std::setprecision(0);
testWithPrefix();
}
Printing
Parsed: "(s8)0" -> 0
Parsed: "(s8)1" -> 1
Parsed: "(s8)127" -> 127
-- (Failing to parse "(s8)128")
Parsed: "(s8)-0" -> 0
Parsed: "(s8)-1" -> -1
Parsed: "(s8)-127" -> -127
Parsed: "(s8)-128" -> -128
-- (Failing to parse "(s8)-255")
Parsed: "(u8)0" -> 0
Parsed: "(u8)1" -> 1
Parsed: "(u8)127" -> 127
Parsed: "(u8)128" -> 128
Parsed: "(u8)255" -> 255
-- (Failing to parse "(u8)256")
-- (Failing to parse "(u8)-0")
Parsed: "(c)0" -> 0
Parsed: "(c)1" -> 1
Parsed: "(c)127" -> 127
-- (Failing to parse "(c)128")
Parsed: "(c)-0" -> 0
Parsed: "(c)-1" -> -1
Parsed: "(c)-127" -> -127
Parsed: "(c)-128" -> -128
-- (Failing to parse "(c)-255")
-- (Failing to parse "(i16)0")
-- (Failing to parse "(i16)-0")
Parsed: "(u16)0" -> 0
Parsed: "(u16)1" -> 1
Parsed: "(u16)127" -> 127
Parsed: "(u16)128" -> 128
Parsed: "(u16)255" -> 255
Parsed: "(u16)256" -> 256
Parsed: "(u16)32767" -> 32767
Parsed: "(u16)32768" -> 32768
Parsed: "(u16)65535" -> 65535
-- (Failing to parse "(u16)65536")
-- (Failing to parse "(u16)-0")
Parsed: "(s32)0" -> 0
Parsed: "(s32)1" -> 1
Parsed: "(s32)127" -> 127
Parsed: "(s32)128" -> 128
Parsed: "(s32)255" -> 255
Parsed: "(s32)256" -> 256
Parsed: "(s32)32767" -> 32767
Parsed: "(s32)32768" -> 32768
Parsed: "(s32)65535" -> 65535
Parsed: "(s32)65536" -> 65536
Parsed: "(s32)2147483647" -> 2147483647
-- (Failing to parse "(s32)2147483648")
Parsed: "(s32)-0" -> 0
Parsed: "(s32)-1" -> -1
Parsed: "(s32)-127" -> -127
Parsed: "(s32)-128" -> -128
Parsed: "(s32)-255" -> -255
Parsed: "(s32)-256" -> -256
Parsed: "(s32)-32767" -> -32767
Parsed: "(s32)-32768" -> -32768
Parsed: "(s32)-65535" -> -65535
Parsed: "(s32)-65536" -> -65536
Parsed: "(s32)-2147483647" -> -2147483647
Parsed: "(s32)-2147483648" -> -2147483648
-- (Failing to parse "(s32)-4294967295")
Parsed: "(u32)0" -> 0
Parsed: "(u32)1" -> 1
Parsed: "(u32)127" -> 127
Parsed: "(u32)128" -> 128
Parsed: "(u32)255" -> 255
Parsed: "(u32)256" -> 256
Parsed: "(u32)32767" -> 32767
Parsed: "(u32)32768" -> 32768
Parsed: "(u32)65535" -> 65535
Parsed: "(u32)65536" -> 65536
Parsed: "(u32)2147483647" -> 2147483647
Parsed: "(u32)2147483648" -> 2147483648
Parsed: "(u32)4294967295" -> 4294967295
-- (Failing to parse "(u32)4294967296")
-- (Failing to parse "(u32)-0")
Parsed: "(s64)0" -> 0
Parsed: "(s64)1" -> 1
Parsed: "(s64)127" -> 127
Parsed: "(s64)128" -> 128
Parsed: "(s64)255" -> 255
Parsed: "(s64)256" -> 256
Parsed: "(s64)32767" -> 32767
Parsed: "(s64)32768" -> 32768
Parsed: "(s64)65535" -> 65535
Parsed: "(s64)65536" -> 65536
Parsed: "(s64)2147483647" -> 2147483647
Parsed: "(s64)2147483648" -> 2147483648
Parsed: "(s64)4294967295" -> 4294967295
Parsed: "(s64)4294967296" -> 4294967296
Parsed: "(s64)9223372036854775807" -> 9223372036854775807
-- (Failing to parse "(s64)9223372036854775808")
Parsed: "(s64)-0" -> 0
Parsed: "(s64)-1" -> -1
Parsed: "(s64)-127" -> -127
Parsed: "(s64)-128" -> -128
Parsed: "(s64)-255" -> -255
Parsed: "(s64)-256" -> -256
Parsed: "(s64)-32767" -> -32767
Parsed: "(s64)-32768" -> -32768
Parsed: "(s64)-65535" -> -65535
Parsed: "(s64)-65536" -> -65536
Parsed: "(s64)-2147483647" -> -2147483647
Parsed: "(s64)-2147483648" -> -2147483648
Parsed: "(s64)-4294967295" -> -4294967295
Parsed: "(s64)-4294967296" -> -4294967296
Parsed: "(s64)-9223372036854775807" -> -9223372036854775807
Parsed: "(s64)-9223372036854775808" -> -9223372036854775808
-- (Failing to parse "(s64)-18446744073709551615")
Parsed: "(u64)0" -> 0
Parsed: "(u64)1" -> 1
Parsed: "(u64)127" -> 127
Parsed: "(u64)128" -> 128
Parsed: "(u64)255" -> 255
Parsed: "(u64)256" -> 256
Parsed: "(u64)32767" -> 32767
Parsed: "(u64)32768" -> 32768
Parsed: "(u64)65535" -> 65535
Parsed: "(u64)65536" -> 65536
Parsed: "(u64)2147483647" -> 2147483647
Parsed: "(u64)2147483648" -> 2147483648
Parsed: "(u64)4294967295" -> 4294967295
Parsed: "(u64)4294967296" -> 4294967296
Parsed: "(u64)9223372036854775807" -> 9223372036854775807
Parsed: "(u64)9223372036854775808" -> 9223372036854775808
Parsed: "(u64)18446744073709551615" -> 18446744073709551615
-- (Failing to parse "(u64)18446744073709551616")
-- (Failing to parse "(u64)-0")
Parsed: "(s128)0" -> 0
Parsed: "(s128)1" -> 1
Parsed: "(s128)127" -> 127
Parsed: "(s128)128" -> 128
Parsed: "(s128)255" -> 255
Parsed: "(s128)256" -> 256
Parsed: "(s128)32767" -> 32767
Parsed: "(s128)32768" -> 32768
Parsed: "(s128)65535" -> 65535
Parsed: "(s128)65536" -> 65536
Parsed: "(s128)2147483647" -> 2147483647
Parsed: "(s128)2147483648" -> 2147483648
Parsed: "(s128)4294967295" -> 4294967295
Parsed: "(s128)4294967296" -> 4294967296
Parsed: "(s128)9223372036854775807" -> 9223372036854775807
Parsed: "(s128)9223372036854775808" -> 9223372036854775808
Parsed: "(s128)18446744073709551615" -> 18446744073709551615
Parsed: "(s128)18446744073709551616" -> 18446744073709551616
Parsed: "(s128)170141183460469231731687303715884105727" -> 170141183460469231731687303715884105728
-- (Failing to parse "(s128)170141183460469231731687303715884105728")
Parsed: "(s128)-0" -> 0
Parsed: "(s128)-1" -> -1
Parsed: "(s128)-127" -> -127
Parsed: "(s128)-128" -> -128
Parsed: "(s128)-255" -> -255
Parsed: "(s128)-256" -> -256
Parsed: "(s128)-32767" -> -32767
Parsed: "(s128)-32768" -> -32768
Parsed: "(s128)-65535" -> -65535
Parsed: "(s128)-65536" -> -65536
Parsed: "(s128)-2147483647" -> -2147483647
Parsed: "(s128)-2147483648" -> -2147483648
Parsed: "(s128)-4294967295" -> -4294967295
Parsed: "(s128)-4294967296" -> -4294967296
Parsed: "(s128)-9223372036854775807" -> -9223372036854775807
Parsed: "(s128)-9223372036854775808" -> -9223372036854775808
Parsed: "(s128)-18446744073709551615" -> -18446744073709551615
Parsed: "(s128)-18446744073709551616" -> -18446744073709551616
Parsed: "(s128)-170141183460469231731687303715884105727" -> -170141183460469231731687303715884105728
Parsed: "(s128)-170141183460469231731687303715884105728" -> -170141183460469231731687303715884105728
-- (Failing to parse "(s128)--123e+45")
Parsed: "(u128)0" -> 0
Parsed: "(u128)1" -> 1
Parsed: "(u128)127" -> 127
Parsed: "(u128)128" -> 128
Parsed: "(u128)255" -> 255
Parsed: "(u128)256" -> 256
Parsed: "(u128)32767" -> 32767
Parsed: "(u128)32768" -> 32768
Parsed: "(u128)65535" -> 65535
Parsed: "(u128)65536" -> 65536
Parsed: "(u128)2147483647" -> 2147483647
Parsed: "(u128)2147483648" -> 2147483648
Parsed: "(u128)4294967295" -> 4294967295
Parsed: "(u128)4294967296" -> 4294967296
Parsed: "(u128)9223372036854775807" -> 9223372036854775807
Parsed: "(u128)9223372036854775808" -> 9223372036854775808
Parsed: "(u128)18446744073709551615" -> 18446744073709551615
Parsed: "(u128)18446744073709551616" -> 18446744073709551616
Parsed: "(u128)170141183460469231731687303715884105727" -> 170141183460469231731687303715884105728
Parsed: "(u128)170141183460469231731687303715884105728" -> 170141183460469231731687303715884105728
-- (Failing to parse "(u128)-123e+45")
-- (Failing to parse "(u128)-0")
Parsed: "0" -> 0
Parsed: "1" -> 1
Parsed: "127" -> 127
Parsed: "128" -> 128
Parsed: "255" -> 255
Parsed: "256" -> 256
Parsed: "32767" -> 32767
Parsed: "32768" -> 32768
Parsed: "65535" -> 65535
Parsed: "65536" -> 65536
Parsed: "2147483647" -> 2147483647
Parsed: "2147483648" -> 2147483648
Parsed: "4294967295" -> 4294967295
Parsed: "4294967296" -> 4294967296
Parsed: "9223372036854775807" -> 9223372036854775807
Parsed: "9223372036854775808" -> 9223372036854775808
Parsed: "18446744073709551615" -> 18446744073709551615
Parsed: "18446744073709551616" -> 18446744073709551616
Parsed: "170141183460469231731687303715884105727" -> 170141183460469231731687303715884105728
Parsed: "170141183460469231731687303715884105728" -> 170141183460469231731687303715884105728
Parsed: "-123e+45" -> -123000000000000000005919784386968639946966958080
(mismatch: -122999999999999999996016264072685597747773964288
Parsed: "-0" -> -0
Parsed: "-1" -> -1
Parsed: "-127" -> -127
Parsed: "-128" -> -128
Parsed: "-255" -> -255
Parsed: "-256" -> -256
Parsed: "-32767" -> -32767
Parsed: "-32768" -> -32768
Parsed: "-65535" -> -65535
Parsed: "-65536" -> -65536
Parsed: "-2147483647" -> -2147483647
Parsed: "-2147483648" -> -2147483648
Parsed: "-4294967295" -> -4294967295
Parsed: "-4294967296" -> -4294967296
Parsed: "-9223372036854775807" -> -9223372036854775807
Parsed: "-9223372036854775808" -> -9223372036854775808
Parsed: "-18446744073709551615" -> -18446744073709551615
Parsed: "-18446744073709551616" -> -18446744073709551616
Parsed: "-170141183460469231731687303715884105727" -> -170141183460469231731687303715884105728
Parsed: "-170141183460469231731687303715884105728" -> -170141183460469231731687303715884105728
-- (Failing to parse "--123e+45")