fix: allow long binary integer and leading zeros

This commit is contained in:
ToruNiina
2023-02-12 16:21:48 +09:00
parent 565f43c484
commit 15346114ef

View File

@@ -57,20 +57,42 @@ parse_binary_integer(location& loc)
{ {
auto str = token.unwrap().str(); auto str = token.unwrap().str();
assert(str.size() > 2); // minimum -> 0b1 assert(str.size() > 2); // minimum -> 0b1
if(64 <= str.size()) assert(str.at(0) == '0' && str.at(1) == 'b');
// skip all the zeros and `_` locating at the MSB
str.erase(str.begin(), std::find_if(
str.begin() + 2, // to skip prefix `0b`
str.end(),
[](const char c) { return c == '1'; })
);
assert(str.empty() || str.front() == '1');
// since toml11 uses int64_t, 64bit (unsigned) input cannot be read.
if(64 + std::count(str.begin(), str.end(), '_') <= str.size())
{ {
// since toml11 uses int64_t, 64bit (unsigned) input cannot be read.
loc.reset(first); loc.reset(first);
return err(format_underline("toml::parse_binary_integer:", return err(format_underline("toml::parse_binary_integer: "
{{source_location(loc), "too large input (> int64_t)"}})); "only signed 64bit integer is available",
{{source_location(loc), "too large input (> int64_t)"}}));
} }
integer retval(0), base(1); integer retval(0), base(1);
for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i) for(auto i(str.rbegin()), e(str.rend()); i!=e; ++i)
{ {
if (*i == '1'){retval += base; base *= 2;} if(*i == '1')
else if(*i == '0'){base *= 2;} {
else if(*i == '_'){/* do nothing. */} retval += base;
else // internal error. base *= 2;
}
else if(*i == '0')
{
base *= 2;
}
else if(*i == '_')
{
// do nothing.
}
else // should be detected by lex_bin_int. [[unlikely]]
{ {
throw internal_error(format_underline( throw internal_error(format_underline(
"toml::parse_binary_integer: internal error", "toml::parse_binary_integer: internal error",