Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
c06ea7ab
Commit
c06ea7ab
authored
Mar 21, 2014
by
Damien George
Browse files
py: Implement parsing of infinity and nan for floats.
parent
1609f855
Changes
4
Hide whitespace changes
Inline
Side-by-side
py/objfloat.c
View file @
c06ea7ab
...
...
@@ -38,7 +38,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
// a string, parse it
uint
l
;
const
char
*
s
=
mp_obj_str_get_data
(
args
[
0
],
&
l
);
return
mp_parse_num_decimal
(
s
,
l
);
return
mp_parse_num_decimal
(
s
,
l
,
false
);
}
else
if
(
MP_OBJ_IS_TYPE
(
args
[
0
],
&
mp_type_float
))
{
return
args
[
0
];
}
else
{
...
...
py/parsenum.c
View file @
c06ea7ab
...
...
@@ -9,6 +9,10 @@
#include
"parsenumbase.h"
#include
"parsenum.h"
#if MICROPY_ENABLE_FLOAT
#include
<math.h>
#endif
#if defined(UNIX)
#include
<ctype.h>
...
...
@@ -84,64 +88,120 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
#define PARSE_DEC_IN_FRAC (2)
#define PARSE_DEC_IN_EXP (3)
mp_obj_t
mp_parse_num_decimal
(
const
char
*
str
,
uint
len
)
{
mp_obj_t
mp_parse_num_decimal
(
const
char
*
str
,
uint
len
,
bool
allow_imag
)
{
#if MICROPY_ENABLE_FLOAT
int
in
=
PARSE_DEC_IN_INTG
;
const
char
*
top
=
str
+
len
;
mp_float_t
dec_val
=
0
;
bool
exp_neg
=
false
;
int
exp_val
=
0
;
int
exp_extra
=
0
;
bool
dec_neg
=
false
;
bool
imag
=
false
;
const
char
*
top
=
str
+
len
;
for
(;
str
<
top
;
str
++
)
{
int
dig
=
*
str
;
if
(
'0'
<=
dig
&&
dig
<=
'9'
)
{
dig
-=
'0'
;
if
(
in
==
PARSE_DEC_IN_EXP
)
{
exp_val
=
10
*
exp_val
+
dig
;
}
else
{
dec_val
=
10
*
dec_val
+
dig
;
if
(
in
==
PARSE_DEC_IN_FRAC
)
{
exp_extra
-=
1
;
}
// skip leading space
for
(;
str
<
top
&&
isspace
(
*
str
);
str
++
)
{
}
// get optional sign
if
(
str
<
top
)
{
if
(
*
str
==
'+'
)
{
str
++
;
}
else
if
(
*
str
==
'-'
)
{
str
++
;
dec_neg
=
true
;
}
}
// determine what the string is
if
(
str
<
top
&&
(
str
[
0
]
|
0x20
)
==
'i'
)
{
// string starts with 'i', should be 'inf' or 'infinity' (case insensitive)
if
(
str
+
2
<
top
&&
(
str
[
1
]
|
0x20
)
==
'n'
&&
(
str
[
2
]
|
0x20
)
==
'f'
)
{
// inf
str
+=
3
;
dec_val
=
INFINITY
;
if
(
str
+
4
<
top
&&
(
str
[
0
]
|
0x20
)
==
'i'
&&
(
str
[
1
]
|
0x20
)
==
'n'
&&
(
str
[
2
]
|
0x20
)
==
'i'
&&
(
str
[
3
]
|
0x20
)
==
't'
&&
(
str
[
4
]
|
0x20
)
==
'y'
)
{
// infinity
str
+=
5
;
}
}
else
if
(
in
==
PARSE_DEC_IN_INTG
&&
dig
==
'.'
)
{
in
=
PARSE_DEC_IN_FRAC
;
}
else
if
(
in
!=
PARSE_DEC_IN_EXP
&&
(
dig
==
'E'
||
dig
==
'e'
))
{
in
=
PARSE_DEC_IN_EXP
;
if
(
str
[
1
]
==
'+'
)
{
str
++
;
}
else
if
(
str
[
1
]
==
'-'
)
{
}
}
else
if
(
str
<
top
&&
(
str
[
0
]
|
0x20
)
==
'n'
)
{
// string starts with 'n', should be 'nan' (case insensitive)
if
(
str
+
2
<
top
&&
(
str
[
1
]
|
0x20
)
==
'a'
&&
(
str
[
2
]
|
0x20
)
==
'n'
)
{
// NaN
str
+=
3
;
dec_val
=
MICROPY_FLOAT_C_FUN
(
nan
)(
""
);
}
}
else
{
// parse the digits
int
in
=
PARSE_DEC_IN_INTG
;
bool
exp_neg
=
false
;
int
exp_val
=
0
;
int
exp_extra
=
0
;
for
(;
str
<
top
;
str
++
)
{
int
dig
=
*
str
;
if
(
'0'
<=
dig
&&
dig
<=
'9'
)
{
dig
-=
'0'
;
if
(
in
==
PARSE_DEC_IN_EXP
)
{
exp_val
=
10
*
exp_val
+
dig
;
}
else
{
dec_val
=
10
*
dec_val
+
dig
;
if
(
in
==
PARSE_DEC_IN_FRAC
)
{
exp_extra
-=
1
;
}
}
}
else
if
(
in
==
PARSE_DEC_IN_INTG
&&
dig
==
'.'
)
{
in
=
PARSE_DEC_IN_FRAC
;
}
else
if
(
in
!=
PARSE_DEC_IN_EXP
&&
((
dig
|
0x20
)
==
'e'
))
{
in
=
PARSE_DEC_IN_EXP
;
if
(
str
[
1
]
==
'+'
)
{
str
++
;
}
else
if
(
str
[
1
]
==
'-'
)
{
str
++
;
exp_neg
=
true
;
}
}
else
if
(
allow_imag
&&
(
dig
|
0x20
)
==
'j'
)
{
str
++
;
exp_neg
=
true
;
imag
=
true
;
break
;
}
else
{
// unknown character
break
;
}
}
else
if
(
dig
==
'J'
||
dig
==
'j'
)
{
str
++
;
imag
=
true
;
break
;
}
else
{
// unknown character
break
;
}
// work out the exponent
if
(
exp_neg
)
{
exp_val
=
-
exp_val
;
}
exp_val
+=
exp_extra
;
// apply the exponent
for
(;
exp_val
>
0
;
exp_val
--
)
{
dec_val
*=
10
;
}
for
(;
exp_val
<
0
;
exp_val
++
)
{
dec_val
*=
0
.
1
;
}
}
if
(
*
str
!=
0
)
{
nlr_jump
(
mp_obj_new_exception_msg
(
&
mp_type_SyntaxError
,
"invalid syntax for number"
));
}
if
(
exp_neg
)
{
exp_val
=
-
exp_val
;
// negate value if needed
if
(
dec_neg
)
{
dec_val
=
-
dec_val
;
}
exp_val
+=
exp_extra
;
for
(;
exp_val
>
0
;
exp_val
--
)
{
dec_val
*=
10
;
// skip trailing space
for
(;
str
<
top
&&
isspace
(
*
str
);
str
++
)
{
}
for
(;
exp_val
<
0
;
exp_val
++
)
{
dec_val
*=
0
.
1
;
// check we reached the end of the string
if
(
str
!=
top
)
{
nlr_jump
(
mp_obj_new_exception_msg
(
&
mp_type_SyntaxError
,
"invalid syntax for number"
));
}
// return the object
if
(
imag
)
{
return
mp_obj_new_complex
(
0
,
dec_val
);
}
else
{
return
mp_obj_new_float
(
dec_val
);
}
#else
nlr_jump
(
mp_obj_new_exception_msg
(
&
mp_type_SyntaxError
,
"decimal numbers not supported"
));
#endif
...
...
py/parsenum.h
View file @
c06ea7ab
mp_obj_t
mp_parse_num_integer
(
const
char
*
restrict
str
,
uint
len
,
int
base
);
mp_obj_t
mp_parse_num_decimal
(
const
char
*
str
,
uint
len
);
mp_obj_t
mp_parse_num_decimal
(
const
char
*
str
,
uint
len
,
bool
allow_imag
);
py/runtime.c
View file @
c06ea7ab
...
...
@@ -375,7 +375,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
DEBUG_OP_printf
(
"load '%s'
\n
"
,
qstr_str
(
qstr
));
uint
len
;
const
byte
*
data
=
qstr_data
(
qstr
,
&
len
);
return
mp_parse_num_decimal
((
const
char
*
)
data
,
len
);
return
mp_parse_num_decimal
((
const
char
*
)
data
,
len
,
true
);
}
mp_obj_t
rt_load_const_str
(
qstr
qstr
)
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment