This patch to 1.8.7 allows for the parsing of floating point literals 
that start with a decimal point.
(Just as it was possible in the bad old days of MRI 1.6.x :-)
These numbers are flagged with a (normally suppressed) warning to allow 
one to check compatibility with unpatched Rubies.

Background:
We use a variant of IRB as an command interpreter.  Users are not 
programmers.  They expect .1 and the like to be accepted as valid 
floating point values.  I'm in the process of moving our app from 1.6.8 
to 1.8.7

===========================

diff --git a/parse.y b/parse.y
index df19699..3d7af5e 100644
--- a/parse.y
+++ b/parse.y
@@ -7,6 +7,7 @@
    created at: Fri May 28 18:02:42 JST 1993

    Copyright (C) 1993-2003 Yukihiro Matsumoto
+  Revised:  Oct 13, 2011 brent / mbari.org -- accept leading dot in float 
literal

  **********************************************************************/

@@ -144,7 +145,6 @@ static NODE *block_append();
  static NODE *list_append();
  static NODE *list_concat();
  static NODE *arg_concat();
-static NODE *arg_prepend();
  static NODE *literal_concat();
  static NODE *new_evstr();
  static NODE *evstr2dstr();
@@ -3251,6 +3251,99 @@ parse_string(quote)
      return tSTRING_CONTENT;
  }

+
+static void
+trailing_uc(int nondigit)
+{
+   char tmp[30];
+   sprintf(tmp, "trailing `%c' in number", nondigit);
+   yyerror(tmp);
+}
+
+static int
+parse_decimal(int c, int nondigit)
+{
+    int is_float, seen_point, seen_e;
+
+    is_float = seen_point = seen_e = 0;
+    for (;;) {
+    switch (c) {
+      case '0': case '1': case '2': case '3': case '4':
+      case '5': case '6': case '7': case '8': case '9':
+        nondigit = 0;
+        tokadd(c);
+        break;
+
+      case '.':
+        if (nondigit)
+              trailing_uc(nondigit);
+        if (seen_point || seen_e) {
+        goto decode_num;
+        }
+        else {
+        int c0 = nextc();
+        if (!ISDIGIT(c0)) {
+            pushback(c0);
+            goto decode_num;
+        }
+        c = c0;
+        }
+        tokadd('.');
+        tokadd(c);
+        is_float++;
+        seen_point++;
+        nondigit = 0;
+        break;
+
+      case 'e':
+      case 'E':
+        if (nondigit) {
+        pushback(c);
+        c = nondigit;
+        goto decode_num;
+        }
+        if (seen_e) {
+        goto decode_num;
+        }
+        tokadd(c);
+        seen_e++;
+        is_float++;
+        nondigit = c;
+        c = nextc();
+        if (c != '-' && c != '+') continue;
+        tokadd(c);
+        nondigit = c;
+        break;
+
+      case '_':    /* `_' in number just ignored */
+        if (nondigit) goto decode_num;
+        nondigit = c;
+        break;
+
+      default:
+        goto decode_num;
+    }
+    c = nextc();
+    }
+
+  decode_num:
+    pushback(c);
+    tokfix();
+    if (nondigit)
+      trailing_uc(nondigit);
+    if (is_float) {
+    double d = strtod(tok(), 0);
+    if (errno == ERANGE) {
+        rb_warn("Float %s out of range", tok());
+        errno = 0;
+    }
+    yylval.node = NEW_LIT(rb_float_new(d));
+    return tFLOAT;
+    }
+    yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
+    return tINTEGER;
+}
+
  static int
  heredoc_identifier()
  {
@@ -3848,8 +3941,8 @@ yylex()
      return '-';

        case '.':
-    lex_state = EXPR_BEG;
      if ((c = nextc()) == '.') {
+        lex_state = EXPR_BEG;
          if ((c = nextc()) == '.') {
          return tDOT3;
          }
@@ -3858,7 +3951,10 @@ yylex()
      }
      pushback(c);
      if (ISDIGIT(c)) {
-        yyerror("no .<digit> floating literal anymore; put 0 before dot");
+            rb_warning (".<digit> floating literal; put 0 before dot");
+        newtok();
+            lex_state = EXPR_END;
+            return parse_decimal('.', 0);
      }
      lex_state = EXPR_DOT;
      return '.';
@@ -3867,9 +3963,8 @@ yylex()
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
      {
-        int is_float, seen_point, seen_e, nondigit;
+        int nondigit = 0;

-        is_float = seen_point = seen_e = nondigit = 0;
          lex_state = EXPR_END;
          newtok();
          if (c == '-' || c == '+') {
@@ -3899,7 +3994,8 @@ yylex()
              if (toklen() == start) {
              yyerror("numeric literal without digits");
              }
-            else if (nondigit) goto trailing_uc;
+            else if (nondigit)
+                      trailing_uc(nondigit);
              yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 16, Qfalse));
              return tINTEGER;
          }
@@ -3923,7 +4019,8 @@ yylex()
              if (toklen() == start) {
              yyerror("numeric literal without digits");
              }
-            else if (nondigit) goto trailing_uc;
+            else if (nondigit)
+                      trailing_uc(nondigit);
              yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 2, Qfalse));
              return tINTEGER;
          }
@@ -3947,7 +4044,8 @@ yylex()
              if (toklen() == start) {
              yyerror("numeric literal without digits");
              }
-            else if (nondigit) goto trailing_uc;
+            else if (nondigit)
+                      trailing_uc(nondigit);
              yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
              return tINTEGER;
          }
@@ -3979,13 +4077,14 @@ yylex()
              if (toklen() > start) {
              pushback(c);
              tokfix();
-            if (nondigit) goto trailing_uc;
+            if (nondigit)
+                          trailing_uc(nondigit);
              yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 8, Qfalse));
              return tINTEGER;
              }
              if (nondigit) {
              pushback(c);
-            goto trailing_uc;
+            trailing_uc(nondigit);
              }
          }
          if (c > '7' && c <= '9') {
@@ -4001,87 +4100,8 @@ yylex()
              return tINTEGER;
          }
          }
-
-        for (;;) {
-        switch (c) {
-          case '0': case '1': case '2': case '3': case '4':
-          case '5': case '6': case '7': case '8': case '9':
-            nondigit = 0;
-            tokadd(c);
-            break;
-
-          case '.':
-            if (nondigit) goto trailing_uc;
-            if (seen_point || seen_e) {
-            goto decode_num;
-            }
-            else {
-            int c0 = nextc();
-            if (!ISDIGIT(c0)) {
-                pushback(c0);
-                goto decode_num;
-            }
-            c = c0;
-            }
-            tokadd('.');
-            tokadd(c);
-            is_float++;
-            seen_point++;
-            nondigit = 0;
-            break;
-
-          case 'e':
-          case 'E':
-            if (nondigit) {
-            pushback(c);
-            c = nondigit;
-            goto decode_num;
-            }
-            if (seen_e) {
-            goto decode_num;
-            }
-            tokadd(c);
-            seen_e++;
-            is_float++;
-            nondigit = c;
-            c = nextc();
-            if (c != '-' && c != '+') continue;
-            tokadd(c);
-            nondigit = c;
-            break;
-
-          case '_':    /* `_' in number just ignored */
-            if (nondigit) goto decode_num;
-            nondigit = c;
-            break;
-
-          default:
-            goto decode_num;
-        }
-        c = nextc();
-        }
-
-      decode_num:
-        pushback(c);
-        tokfix();
-        if (nondigit) {
-        char tmp[30];
-          trailing_uc:
-        sprintf(tmp, "trailing `%c' in number", nondigit);
-        yyerror(tmp);
-        }
-        if (is_float) {
-        double d = strtod(tok(), 0);
-        if (errno == ERANGE) {
-            rb_warn("Float %s out of range", tok());
-            errno = 0;
-        }
-        yylval.node = NEW_LIT(rb_float_new(d));
-        return tFLOAT;
-        }
-        yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
-        return tINTEGER;
-    }
+            return parse_decimal(c, nondigit);
+         }

        case ']':
        case '}':
@@ -5646,27 +5666,6 @@ arg_blk_pass(node1, node2)
  }

  static NODE*
-arg_prepend(node1, node2)
-    NODE *node1, *node2;
-{
-    switch (nd_type(node2)) {
-      case NODE_ARRAY:
-    return list_concat(NEW_LIST(node1), node2);
-
-      case NODE_SPLAT:
-    return arg_concat(node1, node2->nd_head);
-
-      case NODE_BLOCK_PASS:
-    node2->nd_body = arg_prepend(node1, node2->nd_body);
-    return node2;
-
-      default:
-    rb_bug("unknown nodetype(%d) for arg_prepend", nd_type(node2));
-    }
-    return 0;            /* not reached */
-}
-
-static NODE*
  new_call(r,m,a)
      NODE *r;
      ID m;