]> granicus.if.org Git - python/commitdiff
SF patch #455966: Allow leading 0 in float/imag literals.
authorTim Peters <tim.peters@gmail.com>
Thu, 30 Aug 2001 20:51:59 +0000 (20:51 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 30 Aug 2001 20:51:59 +0000 (20:51 +0000)
Consequences for Jython still unknown (but raised on Jython-Dev).

Doc/ref/ref2.tex
Lib/test/test_compile.py
Lib/tokenize.py
Misc/NEWS
Parser/tokenizer.c

index 3ccfaefe2608e39c3e30fa8fb68d96d8f849002d..8b96055da1e1a6aa7f83cc6348bb19647488b2b1 100644 (file)
@@ -517,26 +517,26 @@ definitions:
   \production{pointfloat}
              {[\token{intpart}] \token{fraction} | \token{intpart} "."}
   \production{exponentfloat}
-             {(\token{nonzerodigit} \token{digit}* | \token{pointfloat})
+             {(\token{intpart} | \token{pointfloat})
               \token{exponent}}
   \production{intpart}
-             {\token{nonzerodigit} \token{digit}* | "0"}
+             {\token{digit}+}
   \production{fraction}
              {"." \token{digit}+}
   \production{exponent}
              {("e" | "E") ["+" | "-"] \token{digit}+}
 \end{productionlist}
 
-Note that the integer part of a floating point number cannot look like
-an octal integer, though the exponent may look like an octal literal
-but will always be interpreted using radix 10.  For example,
-\samp{1e010} is legal, while \samp{07.1} is a syntax error.
+Note that the integer and exponent parts of floating point numbers
+can look like octal integers, but are interpreted using radix 10.  For
+example, \samp{077e010} is legal, and denotes the same number
+as \samp{77e10}.
 The allowed range of floating point literals is
 implementation-dependent.
 Some examples of floating point literals:
 
 \begin{verbatim}
-3.14    10.    .001    1e100    3.14e-10
+3.14    10.    .001    1e100    3.14e-10    0e0
 \end{verbatim}
 
 Note that numeric literals do not include a sign; a phrase like
index 0276ba6bee620fc6ca7005cb711a737f7277ec08..9f20ba1377d798e8ed9e8e515b1924a4833fa0a4 100644 (file)
@@ -65,3 +65,47 @@ expect_error("2e")
 expect_error("2.0e+")
 expect_error("1e-")
 expect_error("3-4e/21")
+
+
+if verbose:
+    print "testing literals with leading zeroes"
+
+def expect_same(test_source, expected):
+    got = eval(test_source)
+    if got != expected:
+        raise TestFailed("eval(%r) gave %r, but expected %r" %
+                         (test_source, got, expected))
+
+expect_error("077787")
+expect_error("0xj")
+expect_error("0x.")
+expect_error("0e")
+expect_same("0777", 511)
+expect_same("0777L", 511)
+expect_same("000777", 511)
+expect_same("0xff", 255)
+expect_same("0xffL", 255)
+expect_same("0XfF", 255)
+expect_same("0777.", 777)
+expect_same("0777.0", 777)
+expect_same("000000000000000000000000000000000000000000000000000777e0", 777)
+expect_same("0777e1", 7770)
+expect_same("0e0", 0)
+expect_same("0000E-012", 0)
+expect_same("09.5", 9.5)
+expect_same("0777j", 777j)
+expect_same("00j", 0j)
+expect_same("00.0", 0)
+expect_same("0e3", 0)
+expect_same("090000000000000.", 90000000000000.)
+expect_same("090000000000000.0000000000000000000000", 90000000000000.)
+expect_same("090000000000000e0", 90000000000000.)
+expect_same("090000000000000e-0", 90000000000000.)
+expect_same("090000000000000j", 90000000000000j)
+expect_error("090000000000000")  # plain octal literal w/ decimal digit
+expect_error("080000000000000")  # plain octal literal w/ decimal digit
+expect_error("000000000000009")  # plain octal literal w/ decimal digit
+expect_error("000000000000008")  # plain octal literal w/ decimal digit
+expect_same("000000000000007", 7)
+expect_same("000000000000008.", 8.)
+expect_same("000000000000009.", 9.)
index b952b365c2a856142157fb9caef38608641b8248..da2bcd2c0c1131997c067216a73a3c81644843ac 100644 (file)
@@ -56,9 +56,9 @@ Decnumber = r'[1-9]\d*[lL]?'
 Intnumber = group(Hexnumber, Octnumber, Decnumber)
 Exponent = r'[eE][-+]?\d+'
 Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
-Expfloat = r'[1-9]\d*' + Exponent
+Expfloat = r'\d+' + Exponent
 Floatnumber = group(Pointfloat, Expfloat)
-Imagnumber = group(r'0[jJ]', r'[1-9]\d*[jJ]', Floatnumber + r'[jJ]')
+Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
 Number = group(Imagnumber, Floatnumber, Intnumber)
 
 # Tail end of ' string.
index 7ea6b937364c813d17acc4c02a3b0e6b2341e766..685d6854a9261c23d5143693fc92d821b99c0023 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -3,6 +3,12 @@ What's New in Python 2.2a3?
 
 Core
 
++ The syntax of floating-point and imaginary literals has been
+  liberalized, to allow leading zeroes.  Examples of literals now
+  legal that were SyntaxErrors before:
+
+      00.0    0e3   0100j   07.5   00000000000000000008.
+
 + An old tokenizer bug allowed floating point literals with an incomplete
   exponent, such as 1e and 3.1e-.  Such literals now raise SyntaxError.
 
@@ -27,13 +33,13 @@ API
   module:
 
     - rename Py_TPFLAGS_GC to PyTPFLAGS_HAVE_GC
-    
+
     - use PyObject_GC_New or PyObject_GC_NewVar to allocate objects and
       PyObject_GC_Del to deallocate them
-      
+
     - rename PyObject_GC_Init to PyObject_GC_Track and PyObject_GC_Fini
       to PyObject_GC_UnTrack
-  
+
     - remove PyGC_HEAD_SIZE from object size calculations
 
     - remove calls to PyObject_AS_GC and PyObject_FROM_GC
index 7270629b19b68867ab585de70049313313061b31..324d9b6548c77b7fabe03ace2bf3b5f56b3a3ebb 100644 (file)
@@ -722,7 +722,7 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
        /* Number */
        if (isdigit(c)) {
                if (c == '0') {
-                       /* Hex or octal */
+                       /* Hex or octal -- maybe. */
                        c = tok_nextc(tok);
                        if (c == '.')
                                goto fraction;
@@ -737,13 +737,31 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
                                } while (isxdigit(c));
                        }
                        else {
-                               /* XXX This is broken!  E.g.,
-                                  09.9 should be accepted as float! */
+                               int found_decimal = 0;
                                /* Octal; c is first char of it */
                                /* There's no 'isoctdigit' macro, sigh */
                                while ('0' <= c && c < '8') {
                                        c = tok_nextc(tok);
                                }
+                               if (isdigit(c)) {
+                                       found_decimal = 1;
+                                       do {
+                                               c = tok_nextc(tok);
+                                       } while (isdigit(c));
+                               }
+                               if (c == '.')
+                                       goto fraction;
+                               else if (c == 'e' || c == 'E')
+                                       goto exponent;
+#ifndef WITHOUT_COMPLEX
+                               else if (c == 'j' || c == 'J')
+                                       goto imaginary;
+#endif
+                               else if (found_decimal) {
+                                       tok->done = E_TOKEN;
+                                       tok_backup(tok, c);
+                                       return ERRORTOKEN;
+                               }
                        }
                        if (c == 'l' || c == 'L')
                                c = tok_nextc(tok);
@@ -765,6 +783,7 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
                                        } while (isdigit(c));
                                }
                                if (c == 'e' || c == 'E') {
+               exponent:
                                        /* Exponent part */
                                        c = tok_nextc(tok);
                                        if (c == '+' || c == '-')