raise error on literal ints overflow

This commit is contained in:
blueloveTH 2024-03-04 16:48:47 +08:00
parent e3fa25d774
commit 7f7e1a14ee
4 changed files with 44 additions and 25 deletions

View File

@ -136,6 +136,13 @@ struct Lexer {
std::vector<Token> run();
};
bool parse_int(std::string_view text, i64* out, int base);
enum class IntParsingResult{
Success,
Failure,
Overflow,
};
IntParsingResult parse_int(std::string_view text, i64* out, int base);
} // namespace pkpy

View File

@ -284,9 +284,15 @@ static bool is_unicode_Lo_char(uint32_t c) {
}
// try integer
i64 int_out;
if(parse_int(text, &int_out, -1)){
switch(parse_int(text, &int_out, -1)){
case IntParsingResult::Success:
add_token(TK("@num"), int_out);
return;
case IntParsingResult::Overflow:
SyntaxError("integer literal too large");
return;
case IntParsingResult::Failure:
break; // do nothing
}
}
@ -476,7 +482,7 @@ static bool is_unicode_Lo_char(uint32_t c) {
return std::move(nexts);
}
bool parse_int(std::string_view text, i64* out, int base){
IntParsingResult parse_int(std::string_view text, i64* out, int base){
*out = 0;
const auto f_startswith_2 = [](std::string_view t, const char* prefix) -> bool{
@ -493,63 +499,63 @@ bool parse_int(std::string_view text, i64* out, int base){
if(base == 10){
// 10-base 12334
if(text.length() == 0) return false;
if(text.length() == 0) return IntParsingResult::Failure;
for(char c : text){
if(c >= '0' && c <= '9'){
*out = (*out * 10) + (c - '0');
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else{
return false;
return IntParsingResult::Failure;
}
}
return true;
return IntParsingResult::Success;
}else if(base == 2){
// 2-base 0b101010
if(f_startswith_2(text, "0b")) text.remove_prefix(2);
if(text.length() == 0) return false;
if(text.length() == 0) return IntParsingResult::Failure;
for(char c : text){
if(c == '0' || c == '1'){
*out = (*out << 1) | (c - '0');
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else{
return false;
return IntParsingResult::Failure;
}
}
return true;
return IntParsingResult::Success;
}else if(base == 8){
// 8-base 0o123
if(f_startswith_2(text, "0o")) text.remove_prefix(2);
if(text.length() == 0) return false;
if(text.length() == 0) return IntParsingResult::Failure;
for(char c : text){
if(c >= '0' && c <= '7'){
*out = (*out << 3) | (c - '0');
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else{
return false;
return IntParsingResult::Failure;
}
}
return true;
return IntParsingResult::Success;
}else if(base == 16){
// 16-base 0x123
if(f_startswith_2(text, "0x")) text.remove_prefix(2);
if(text.length() == 0) return false;
if(text.length() == 0) return IntParsingResult::Failure;
for(char c : text){
if(c >= '0' && c <= '9'){
*out = (*out << 4) | (c - '0');
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else if(c >= 'a' && c <= 'f'){
*out = (*out << 4) | (c - 'a' + 10);
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else if(c >= 'A' && c <= 'F'){
*out = (*out << 4) | (c - 'A' + 10);
if(*out < 0) return false; // overflow
if(*out < 0) return IntParsingResult::Overflow;
}else{
return false;
return IntParsingResult::Failure;
}
}
return true;
return IntParsingResult::Success;
}
return false;
return IntParsingResult::Failure;
}
} // namespace pkpy

View File

@ -415,7 +415,7 @@ void init_builtins(VM* _vm) {
sv.remove_prefix(1);
}
i64 val;
if(!parse_int(sv, &val, base)){
if(parse_int(sv, &val, base) != IntParsingResult::Success){
vm->ValueError(_S("invalid literal for int() with base ", base, ": ", s.escape()));
}
if(negative) val = -val;

View File

@ -124,3 +124,9 @@ except ZeroDivisionError:
pass
assert not 1 < 2 > 3
try:
eval("231231312312312312312312312312312312314354657553423345632")
exit(1)
except SyntaxError:
pass