diff --git a/include/pocketpy/lexer.h b/include/pocketpy/lexer.h index 760662ba..f5428346 100644 --- a/include/pocketpy/lexer.h +++ b/include/pocketpy/lexer.h @@ -136,6 +136,13 @@ struct Lexer { std::vector 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 diff --git a/src/lexer.cpp b/src/lexer.cpp index 0a8c0b5f..3d9d7981 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -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)){ - add_token(TK("@num"), int_out); - return; + 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 diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 63f2a15b..790189a1 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -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; diff --git a/tests/01_int.py b/tests/01_int.py index bbab4d31..e8967d69 100644 --- a/tests/01_int.py +++ b/tests/01_int.py @@ -124,3 +124,9 @@ except ZeroDivisionError: pass assert not 1 < 2 > 3 + +try: + eval("231231312312312312312312312312312312314354657553423345632") + exit(1) +except SyntaxError: + pass