Fix parsing of negative numbers

This commit is contained in:
Jason Turner 2017-01-31 15:41:21 -08:00
parent e7a6b2306c
commit 83b7973cb8
3 changed files with 30 additions and 30 deletions

View File

@ -144,21 +144,6 @@ namespace chaiscript {
}; };
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
{
T t = 0;
for (char c = *t_str; (c = *t_str) != 0; ++t_str) {
if (c < '0' || c > '9') {
return t;
}
t *= 10;
t += c - '0';
}
return t;
}
template<typename T> template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
{ {
@ -176,6 +161,16 @@ namespace chaiscript {
} }
}; };
const bool neg = [&](){
if (t_str[0] == '-') {
++t_str;
return true;
} else {
return false;
}
}();
for(; *t_str != '\0'; ++t_str) { for(; *t_str != '\0'; ++t_str) {
char c = *t_str; char c = *t_str;
if (c == '.') { if (c == '.') {
@ -200,7 +195,7 @@ namespace chaiscript {
} }
} }
return final_value(t, base, exponent, neg_exponent); return final_value(t, base, exponent, neg_exponent) * (neg?-1:1);
} }
template<typename T> template<typename T>

View File

@ -722,7 +722,10 @@ namespace chaiscript
} }
} }
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
const bool neg = t_val[0] == '-';
const auto pref = neg?std::string(t_val.begin()+1,t_val.end()):t_val;
const auto val = prefixed?std::string(pref.begin() + 2, pref.end()):pref;
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -739,17 +742,17 @@ namespace chaiscript
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) { if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
return const_var(static_cast<int>(u)); return const_var(static_cast<int>(u) * (neg?-1:1));
} else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) { } else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) {
return const_var(static_cast<unsigned int>(u)); return const_var(static_cast<unsigned int>(u) * (neg?-1:1));
} else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) { } else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) {
return const_var(static_cast<long>(u)); return const_var(static_cast<long>(u) * (neg?-1:1));
} else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) { } else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
return const_var(static_cast<unsigned long>(u)); return const_var(static_cast<unsigned long>(u) * (neg?-1:1));
} else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) { } else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) {
return const_var(static_cast<long long>(u)); return const_var(static_cast<long long>(u) * (neg?-1:1));
} else { } else {
return const_var(static_cast<unsigned long long>(u)); return const_var(static_cast<unsigned long long>(u) * (neg?-1:1));
} }
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
@ -758,13 +761,13 @@ namespace chaiscript
auto u = std::stoull(val,nullptr,base); auto u = std::stoull(val,nullptr,base);
if (u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) { if (u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
return const_var(static_cast<unsigned long>(u)); return const_var(static_cast<unsigned long>(u) * (neg?-1:1));
} else { } else {
return const_var(static_cast<unsigned long long>(u)); return const_var(static_cast<unsigned long long>(u) * (neg?-1:1));
} }
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
// it's just simply too big // it's just simply too big
return const_var(std::numeric_limits<long long>::max()); return const_var(neg?std::numeric_limits<long long>::min():std::numeric_limits<long long>::max());
} }
} }
@ -785,6 +788,7 @@ namespace chaiscript
SkipWS(); SkipWS();
const auto start = m_position; const auto start = m_position;
const bool neg = Char_('-');
if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) {
try { try {
if (Hex_()) { if (Hex_()) {
@ -809,7 +813,7 @@ namespace chaiscript
else { else {
IntSuffix_(); IntSuffix_();
auto match = Position::str(start, m_position); auto match = Position::str(start, m_position);
if (!match.empty() && (match[0] == '0')) { if (!match.empty() && (match[neg?1:0] == '0')) {
auto bv = buildInt(8, match, false); auto bv = buildInt(8, match, false);
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
} }
@ -827,6 +831,7 @@ namespace chaiscript
} }
} }
else { else {
if (neg) { --m_position; }
return false; return false;
} }
} }

View File

@ -600,7 +600,7 @@ struct JSONParser {
break; break;
} }
} }
exp = chaiscript::parse_num<long>( exp_str ); exp = std::stol( exp_str );
} }
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
@ -611,9 +611,9 @@ struct JSONParser {
return JSON(chaiscript::parse_num<double>( val ) * std::pow( 10, exp )); return JSON(chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
} else { } else {
if( !exp_str.empty() ) { if( !exp_str.empty() ) {
return JSON(static_cast<double>(chaiscript::parse_num<long>( val )) * std::pow( 10, exp )); return JSON(static_cast<double>(std::stol( val )) * std::pow( 10, exp ));
} else { } else {
return JSON(chaiscript::parse_num<long>( val )); return JSON(std::stol( val ));
} }
} }
} }