Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d507dab

Browse files
committed
SF patch #455966: Allow leading 0 in float/imag literals.
Consequences for Jython still unknown (but raised on Jython-Dev).
1 parent 21922aa commit d507dab

5 files changed

Lines changed: 84 additions & 15 deletions

File tree

Doc/ref/ref2.tex

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -517,26 +517,26 @@ \subsection{Floating point literals\label{floating}}
517517
\production{pointfloat}
518518
{[\token{intpart}] \token{fraction} | \token{intpart} "."}
519519
\production{exponentfloat}
520-
{(\token{nonzerodigit} \token{digit}* | \token{pointfloat})
520+
{(\token{intpart} | \token{pointfloat})
521521
\token{exponent}}
522522
\production{intpart}
523-
{\token{nonzerodigit} \token{digit}* | "0"}
523+
{\token{digit}+}
524524
\production{fraction}
525525
{"." \token{digit}+}
526526
\production{exponent}
527527
{("e" | "E") ["+" | "-"] \token{digit}+}
528528
\end{productionlist}
529529

530-
Note that the integer part of a floating point number cannot look like
531-
an octal integer, though the exponent may look like an octal literal
532-
but will always be interpreted using radix 10. For example,
533-
\samp{1e010} is legal, while \samp{07.1} is a syntax error.
530+
Note that the integer and exponent parts of floating point numbers
531+
can look like octal integers, but are interpreted using radix 10. For
532+
example, \samp{077e010} is legal, and denotes the same number
533+
as \samp{77e10}.
534534
The allowed range of floating point literals is
535535
implementation-dependent.
536536
Some examples of floating point literals:
537537

538538
\begin{verbatim}
539-
3.14 10. .001 1e100 3.14e-10
539+
3.14 10. .001 1e100 3.14e-10 0e0
540540
\end{verbatim}
541541

542542
Note that numeric literals do not include a sign; a phrase like

Lib/test/test_compile.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,47 @@ def expect_error(s):
6565
expect_error("2.0e+")
6666
expect_error("1e-")
6767
expect_error("3-4e/21")
68+
69+
70+
if verbose:
71+
print "testing literals with leading zeroes"
72+
73+
def expect_same(test_source, expected):
74+
got = eval(test_source)
75+
if got != expected:
76+
raise TestFailed("eval(%r) gave %r, but expected %r" %
77+
(test_source, got, expected))
78+
79+
expect_error("077787")
80+
expect_error("0xj")
81+
expect_error("0x.")
82+
expect_error("0e")
83+
expect_same("0777", 511)
84+
expect_same("0777L", 511)
85+
expect_same("000777", 511)
86+
expect_same("0xff", 255)
87+
expect_same("0xffL", 255)
88+
expect_same("0XfF", 255)
89+
expect_same("0777.", 777)
90+
expect_same("0777.0", 777)
91+
expect_same("000000000000000000000000000000000000000000000000000777e0", 777)
92+
expect_same("0777e1", 7770)
93+
expect_same("0e0", 0)
94+
expect_same("0000E-012", 0)
95+
expect_same("09.5", 9.5)
96+
expect_same("0777j", 777j)
97+
expect_same("00j", 0j)
98+
expect_same("00.0", 0)
99+
expect_same("0e3", 0)
100+
expect_same("090000000000000.", 90000000000000.)
101+
expect_same("090000000000000.0000000000000000000000", 90000000000000.)
102+
expect_same("090000000000000e0", 90000000000000.)
103+
expect_same("090000000000000e-0", 90000000000000.)
104+
expect_same("090000000000000j", 90000000000000j)
105+
expect_error("090000000000000") # plain octal literal w/ decimal digit
106+
expect_error("080000000000000") # plain octal literal w/ decimal digit
107+
expect_error("000000000000009") # plain octal literal w/ decimal digit
108+
expect_error("000000000000008") # plain octal literal w/ decimal digit
109+
expect_same("000000000000007", 7)
110+
expect_same("000000000000008.", 8.)
111+
expect_same("000000000000009.", 9.)

Lib/tokenize.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ def maybe(*choices): return apply(group, choices) + '?'
5656
Intnumber = group(Hexnumber, Octnumber, Decnumber)
5757
Exponent = r'[eE][-+]?\d+'
5858
Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
59-
Expfloat = r'[1-9]\d*' + Exponent
59+
Expfloat = r'\d+' + Exponent
6060
Floatnumber = group(Pointfloat, Expfloat)
61-
Imagnumber = group(r'0[jJ]', r'[1-9]\d*[jJ]', Floatnumber + r'[jJ]')
61+
Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
6262
Number = group(Imagnumber, Floatnumber, Intnumber)
6363

6464
# Tail end of ' string.

Misc/NEWS

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ What's New in Python 2.2a3?
33

44
Core
55

6+
+ The syntax of floating-point and imaginary literals has been
7+
liberalized, to allow leading zeroes. Examples of literals now
8+
legal that were SyntaxErrors before:
9+
10+
00.0 0e3 0100j 07.5 00000000000000000008.
11+
612
+ An old tokenizer bug allowed floating point literals with an incomplete
713
exponent, such as 1e and 3.1e-. Such literals now raise SyntaxError.
814

@@ -27,13 +33,13 @@ API
2733
module:
2834

2935
- rename Py_TPFLAGS_GC to PyTPFLAGS_HAVE_GC
30-
36+
3137
- use PyObject_GC_New or PyObject_GC_NewVar to allocate objects and
3238
PyObject_GC_Del to deallocate them
33-
39+
3440
- rename PyObject_GC_Init to PyObject_GC_Track and PyObject_GC_Fini
3541
to PyObject_GC_UnTrack
36-
42+
3743
- remove PyGC_HEAD_SIZE from object size calculations
3844

3945
- remove calls to PyObject_AS_GC and PyObject_FROM_GC

Parser/tokenizer.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
722722
/* Number */
723723
if (isdigit(c)) {
724724
if (c == '0') {
725-
/* Hex or octal */
725+
/* Hex or octal -- maybe. */
726726
c = tok_nextc(tok);
727727
if (c == '.')
728728
goto fraction;
@@ -737,13 +737,31 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
737737
} while (isxdigit(c));
738738
}
739739
else {
740-
/* XXX This is broken! E.g.,
741-
09.9 should be accepted as float! */
740+
int found_decimal = 0;
742741
/* Octal; c is first char of it */
743742
/* There's no 'isoctdigit' macro, sigh */
744743
while ('0' <= c && c < '8') {
745744
c = tok_nextc(tok);
746745
}
746+
if (isdigit(c)) {
747+
found_decimal = 1;
748+
do {
749+
c = tok_nextc(tok);
750+
} while (isdigit(c));
751+
}
752+
if (c == '.')
753+
goto fraction;
754+
else if (c == 'e' || c == 'E')
755+
goto exponent;
756+
#ifndef WITHOUT_COMPLEX
757+
else if (c == 'j' || c == 'J')
758+
goto imaginary;
759+
#endif
760+
else if (found_decimal) {
761+
tok->done = E_TOKEN;
762+
tok_backup(tok, c);
763+
return ERRORTOKEN;
764+
}
747765
}
748766
if (c == 'l' || c == 'L')
749767
c = tok_nextc(tok);
@@ -765,6 +783,7 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
765783
} while (isdigit(c));
766784
}
767785
if (c == 'e' || c == 'E') {
786+
exponent:
768787
/* Exponent part */
769788
c = tok_nextc(tok);
770789
if (c == '+' || c == '-')

0 commit comments

Comments
 (0)