Browse Source

raise error on literal ints overflow

blueloveTH 2 năm trước cách đây
mục cha
commit
7f7e1a14ee
4 tập tin đã thay đổi với 44 bổ sung25 xóa
  1. 8 1
      include/pocketpy/lexer.h
  2. 29 23
      src/lexer.cpp
  3. 1 1
      src/pocketpy.cpp
  4. 6 0
      tests/01_int.py

+ 8 - 1
include/pocketpy/lexer.h

@@ -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

+ 29 - 23
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

+ 1 - 1
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;

+ 6 - 0
tests/01_int.py

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