**** start-sanitize-chill ****
authorFred Fish <fnf@specifix.com>
Sun, 3 Jan 1993 06:56:08 +0000 (06:56 +0000)
committerFred Fish <fnf@specifix.com>
Sun, 3 Jan 1993 06:56:08 +0000 (06:56 +0000)
* ch-exp.y (FLOAT_LITERAL):  Add token.
* ch-exp.y (literal):  Add FLOAT_LITERAL.
* ch-exp.y (match_float_literal):  New lexer routine.
* ch-exp.y (convert_float):  Remove.
* ch-exp.y (yylex):  Call match_float_literal.
* ch-exp.y (yylex):  Match single '.' after trying
to match floating point literals.
**** end-sanitize-chill ****

gdb/ChangeLog
gdb/ch-exp.y

index bdefc38c8f27d479e7ffd0237f10d881c434a505..e65547a1e3b389edcb68894eb123a9262c273b36 100644 (file)
@@ -1,5 +1,15 @@
 Sat Jan  2 12:16:41 1993  Fred Fish  (fnf@cygnus.com)
 
+       **** start-sanitize-chill ****
+       * ch-exp.y (FLOAT_LITERAL):  Add token.
+       * ch-exp.y (literal):  Add FLOAT_LITERAL.
+       * ch-exp.y (match_float_literal):  New lexer routine.
+       * ch-exp.y (convert_float):  Remove.
+       * ch-exp.y (yylex):  Call match_float_literal.
+       * ch-exp.y (yylex):  Match single '.' after trying
+       to match floating point literals.
+       **** end-sanitize-chill ****
+
        * eval.c (evaluate_subexp):  Add case MULTI_SUBSCRIPT.
        * expprint.c (print_subexp):  Rename BINOP_MULTI_SUBSCRIPT to
        MULTI_SUBSCRIPT.
index e330a9fc661c8185ed6e2a8615c626be6819e10b..6d6ebe7346441ed01ebdbee4947ee711c4b9a7f3 100644 (file)
@@ -144,6 +144,7 @@ yyerror PARAMS ((char *));
 %token <typed_val>     INTEGER_LITERAL
 %token <ulval>         BOOLEAN_LITERAL
 %token <typed_val>     CHARACTER_LITERAL
+%token <dval>          FLOAT_LITERAL
 %token <ssym>          GENERAL_PROCEDURE_NAME
 %token <ssym>          LOCATION_NAME
 %token <voidval>       SET_LITERAL
@@ -457,6 +458,13 @@ literal            :       INTEGER_LITERAL
                          write_exp_elt_longcst ((LONGEST) ($1.val));
                          write_exp_elt_opcode (OP_LONG);
                        }
+               |       FLOAT_LITERAL
+                       {
+                         write_exp_elt_opcode (OP_DOUBLE);
+                         write_exp_elt_type (builtin_type_double);
+                         write_exp_elt_dblcst ($1);
+                         write_exp_elt_opcode (OP_DOUBLE);
+                       }
                |       SET_LITERAL
                        {
                          $$ = 0;       /* FIXME */
@@ -1005,6 +1013,141 @@ decode_integer_literal (valptr, tokptrptr)
     }
 }
 
+/*  If it wasn't for the fact that floating point values can contain '_'
+    characters, we could just let strtod do all the hard work by letting it
+    try to consume as much of the current token buffer as possible and
+    find a legal conversion.  Unfortunately we need to filter out the '_'
+    characters before calling strtod, which we do by copying the other
+    legal chars to a local buffer to be converted.  However since we also
+    need to keep track of where the last unconsumed character in the input
+    buffer is, we have transfer only as many characters as may compose a
+    legal floating point value. */
+    
+static int
+match_float_literal ()
+{
+  char *tokptr = lexptr;
+  char *buf;
+  char *copy;
+  char ch;
+  double dval;
+  extern double strtod ();
+  
+  /* Make local buffer in which to build the string to convert.  This is
+     required because underscores are valid in chill floating point numbers
+     but not in the string passed to strtod to convert.  The string will be
+     no longer than our input string. */
+     
+  copy = buf = (char *) alloca (strlen (tokptr) + 1);
+
+  /* Transfer all leading digits to the conversion buffer, discarding any
+     underscores. */
+
+  while (isdigit (*tokptr) || *tokptr == '_')
+    {
+      if (*tokptr != '_')
+       {
+         *copy++ = *tokptr;
+       }
+      tokptr++;
+    }
+
+  /* Now accept either a '.', or one of [eEdD].  Dot is legal regardless
+     of whether we found any leading digits, and we simply accept it and
+     continue on to look for the fractional part and/or exponent.  One of
+     [eEdD] is legal only if we have seen digits, and means that there
+     is no fractional part.  If we find neither of these, then this is
+     not a floating point number, so return failure. */
+
+  switch (*tokptr++)
+    {
+      case '.':
+        /* Accept and then look for fractional part and/or exponent. */
+       *copy++ = '.';
+       break;
+
+      case 'e':
+      case 'E':
+      case 'd':
+      case 'D':
+       if (copy == buf)
+         {
+           return (0);
+         }
+       *copy++ = 'e';
+       goto collect_exponent;
+       break;
+
+      default:
+       return (0);
+        break;
+    }
+
+  /* We found a '.', copy any fractional digits to the conversion buffer, up
+     to the first nondigit, non-underscore character. */
+
+  while (isdigit (*tokptr) || *tokptr == '_')
+    {
+      if (*tokptr != '_')
+       {
+         *copy++ = *tokptr;
+       }
+      tokptr++;
+    }
+
+  /* Look for an exponent, which must start with one of [eEdD].  If none
+     is found, jump directly to trying to convert what we have collected
+     so far. */
+
+  switch (*tokptr)
+    {
+      case 'e':
+      case 'E':
+      case 'd':
+      case 'D':
+       *copy++ = 'e';
+       tokptr++;
+       break;
+      default:
+       goto convert_float;
+       break;
+    }
+
+  /* Accept an optional '-' or '+' following one of [eEdD]. */
+
+  collect_exponent:
+  if (*tokptr == '+' || *tokptr == '-')
+    {
+      *copy++ = *tokptr++;
+    }
+
+  /* Now copy an exponent into the conversion buffer.  Note that at the 
+     moment underscores are *not* allowed in exponents. */
+
+  while (isdigit (*tokptr))
+    {
+      *copy++ = *tokptr++;
+    }
+
+  /* If we transfered any chars to the conversion buffer, try to interpret its
+     contents as a floating point value.  If any characters remain, then we
+     must not have a valid floating point string. */
+
+  convert_float:
+  *copy = '\0';
+  if (copy != buf)
+      {
+        dval = strtod (buf, &copy);
+        if (*copy == '\0')
+         {
+           yylval.dval = dval;
+           lexptr = tokptr;
+           return (FLOAT_LITERAL);
+         }
+      }
+  return (0);
+}
+
 /* Recognize a character literal.  A character literal is single character
    or a control sequence, enclosed in single quotes.  A control sequence
    is a comma separated list of one or more integer literals, enclosed
@@ -1229,48 +1372,6 @@ match_dollar_tokens ()
   return (GDB_LAST);
 }
 
-#if 0
-static void convert_float ()
-{
-    extern double strtod ();
-    double d;
-    char       tmp[256];
-    char       *p = yytext, *p1 = tmp;
-    char       c;
-    
-    while (c = *p++)
-    {
-       switch (c)
-       {
-       case '_':
-           break;
-       case 'E':
-       case 'd':
-       case 'D':
-           *p1++ = 'e';
-           break;
-       default:
-           *p1++ = c;
-           break;
-       }
-    }
-    *p1 = '\0';
-    d = strtod (tmp, &p1);
-    if (*p1)
-    {
-       /* add error handling here */
-       ;
-    }
-    yylval.dval = d;
-}
-#endif
-
-/* Take care of parsing a number (anything that starts with a digit).
-   Set yylval and return the token type; update lexptr.
-   LEN is the number of characters in it.  */
-
-/*** Needs some error checking for the float case ***/
-
 struct token
 {
   char *operator;
@@ -1329,7 +1430,6 @@ yylex ()
            case '\0':
                return (0);
            case ',':
-           case '.':
            case '=':
            case ';':
            case '!':
@@ -1425,6 +1525,13 @@ yylex ()
            lexptr += 5;
            return (BOOLEAN_LITERAL);
        }
+    /* Look for a float literal before looking for an integer literal, so
+       we match as much of the input stream as possible. */
+    token = match_float_literal ();
+    if (token != 0)
+       {
+           return (token);
+       }
     token = match_integer_literal ();
     if (token != 0)
        {
@@ -1481,6 +1588,15 @@ yylex ()
          }
       }
 
+    /* Catch single character tokens which are not part of some
+       longer token. */
+
+    switch (*lexptr)
+      {
+       case '.':                       /* Not float for example. */
+         return (*lexptr++);
+      }
+
     return (ILLEGAL_TOKEN);
 }