summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/parsenum.c37
-rw-r--r--tests/float/complex1.py12
2 files changed, 44 insertions, 5 deletions
diff --git a/py/parsenum.c b/py/parsenum.c
index 1cfe842577..848a7732d9 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -166,6 +166,12 @@ value_error:
}
}
+enum {
+ REAL_IMAG_STATE_START = 0,
+ REAL_IMAG_STATE_HAVE_REAL = 1,
+ REAL_IMAG_STATE_HAVE_IMAG = 2,
+};
+
typedef enum {
PARSE_DEC_IN_INTG,
PARSE_DEC_IN_FRAC,
@@ -196,7 +202,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
const char *top = str + len;
mp_float_t dec_val = 0;
bool dec_neg = false;
- bool imag = false;
+ unsigned int real_imag_state = REAL_IMAG_STATE_START;
+
+ #if MICROPY_PY_BUILTINS_COMPLEX
+ mp_float_t dec_real = 0;
+parse_start:
+ #endif
// skip leading space
for (; str < top && unichar_isspace(*str); str++) {
@@ -281,7 +292,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
goto value_error;
}
} else if (allow_imag && (dig | 0x20) == 'j') {
- imag = true;
+ real_imag_state |= REAL_IMAG_STATE_HAVE_IMAG;
break;
} else if (dig == '_') {
continue;
@@ -332,18 +343,34 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
// check we reached the end of the string
if (str != top) {
+ #if MICROPY_PY_BUILTINS_COMPLEX
+ if (force_complex && real_imag_state == REAL_IMAG_STATE_START) {
+ // If we've only seen a real so far, keep parsing for the imaginary part.
+ dec_real = dec_val;
+ dec_val = 0;
+ real_imag_state |= REAL_IMAG_STATE_HAVE_REAL;
+ goto parse_start;
+ }
+ #endif
goto value_error;
}
+ #if MICROPY_PY_BUILTINS_COMPLEX
+ if (real_imag_state == REAL_IMAG_STATE_HAVE_REAL) {
+ // We're on the second part, but didn't get the expected imaginary number.
+ goto value_error;
+ }
+ #endif
+
// return the object
#if MICROPY_PY_BUILTINS_COMPLEX
- if (imag) {
- return mp_obj_new_complex(0, dec_val);
+ if (real_imag_state != REAL_IMAG_STATE_START) {
+ return mp_obj_new_complex(dec_real, dec_val);
} else if (force_complex) {
return mp_obj_new_complex(dec_val, 0);
}
#else
- if (imag || force_complex) {
+ if (real_imag_state != REAL_IMAG_STATE_START || force_complex) {
raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, MP_ERROR_TEXT("complex values not supported")), lex);
}
#endif
diff --git a/tests/float/complex1.py b/tests/float/complex1.py
index 139bb0c509..feede0eab3 100644
--- a/tests/float/complex1.py
+++ b/tests/float/complex1.py
@@ -7,6 +7,11 @@ print(complex(1.2j))
print(complex("1"))
print(complex("1.2"))
print(complex("1.2j"))
+print(complex("1+2j"))
+print(complex("-1-2j"))
+print(complex("+1-2j"))
+print(complex(" -1-2j "))
+print(complex(" +1-2j "))
print(complex(1, 2))
print(complex(1j, 2j))
@@ -72,6 +77,13 @@ print(float("-nan") * 1j)
print(float("inf") * (1 + 1j))
print(float("-inf") * (1 + 1j))
+# malformed complex strings
+for test in ("1+2", "1j+2", "1+2j+3", "1+2+3j", "1 + 2j"):
+ try:
+ complex(test)
+ except ValueError:
+ print("ValueError", test)
+
# can't assign to attributes
try:
(1j).imag = 0