New function parse_value() for parsing a value of specified width.
authorBen Pfaff <blp@gnu.org>
Sun, 24 May 2009 18:26:41 +0000 (11:26 -0700)
committerBen Pfaff <blp@gnu.org>
Sun, 7 Jun 2009 04:11:12 +0000 (21:11 -0700)
Occasionally a value of a given width needs to be parsed from syntax.
This commit adds a helper function for doing so and modifies a few pieces
of code to use it.  Probably there are other places where it would be
useful that could not easily be found with "grep".

This commit also renames the range-parser code to value-parser and puts
the new function in there, as a natural generalization.

Suggested by John Darrington.

src/language/dictionary/missing-values.c
src/language/expressions/evaluate.c
src/language/lexer/automake.mk
src/language/lexer/range-parser.c [deleted file]
src/language/lexer/range-parser.h [deleted file]
src/language/lexer/value-parser.c [new file with mode: 0644]
src/language/lexer/value-parser.h [new file with mode: 0644]
src/language/stats/t-test.q
src/language/xforms/count.c
src/language/xforms/recode.c

index 950abc1528115c0b123fa40568c85f60a770b2ac..66e642eb9707dff3fd908478e651c5dfdafe5fb2 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,8 +26,8 @@
 #include <data/format.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/value-parser.h>
 #include <language/lexer/variable-parser.h>
-#include <language/lexer/range-parser.h>
 #include <libpspp/message.h>
 #include <libpspp/message.h>
 #include <libpspp/str.h>
index d5f5f3871744252ac9f92ad61ec0e78f9a0b73ad..ad108f5a60f151ac678609ef104f82bb88a7e1ac 100644 (file)
@@ -22,6 +22,7 @@
 #include <libpspp/message.h>
 #include <language/expressions/helpers.h>
 #include <language/expressions/private.h>
+#include <language/lexer/value-parser.h>
 #include <libpspp/pool.h>
 
 #include "xalloc.h"
@@ -174,11 +175,8 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
           else
             c = case_unshare_and_resize (c, dict_get_proto (d));
 
-          if (lex_is_number (lexer))
-            case_data_rw (c, v)->f = lex_tokval (lexer);
-          else
-            memcpy (case_str_rw (c, v), ds_data (lex_tokstr (lexer)),
-                    var_get_width (v));
+          if (!parse_value (lexer, case_data_rw (c, v), var_get_width (v)))
+            NOT_REACHED ();
           lex_get (lexer);
 
           if (!lex_force_match (lexer, ')'))
index 0ce371afb8b6c37c36b81478c76108ec70eab3fb..aff3f2a2879d97869affded7a2f260401e657751 100644 (file)
@@ -7,8 +7,8 @@ language_lexer_sources = \
        src/language/lexer/subcommand-list.h \
        src/language/lexer/format-parser.c \
        src/language/lexer/format-parser.h \
-       src/language/lexer/range-parser.c \
-       src/language/lexer/range-parser.h \
+       src/language/lexer/value-parser.c \
+       src/language/lexer/value-parser.h \
        src/language/lexer/variable-parser.c \
        src/language/lexer/variable-parser.h
 
diff --git a/src/language/lexer/range-parser.c b/src/language/lexer/range-parser.c
deleted file mode 100644 (file)
index 4cf21cf..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include "range-parser.h"
-#include <stdbool.h>
-#include <data/data-in.h>
-#include <libpspp/message.h>
-#include "lexer.h"
-#include <libpspp/str.h>
-#include <data/value.h>
-#include <data/format.h>
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-#define N_(msgid) msgid
-
-static bool parse_number (struct lexer *, double *, const enum fmt_type *);
-
-/* Parses and stores a numeric value, or a range of the form "x
-   THRU y".  Open-ended ranges may be specified as "LO(WEST) THRU
-   y" or "x THRU HI(GHEST)".  Sets *X and *Y to the range or the
-   value and returns success.
-
-   Numeric values are always accepted.  If FORMAT is nonnull,
-   then string values are also accepted, and converted to numeric
-   values using *FORMAT. */
-bool
-parse_num_range (struct lexer *lexer,
-                 double *x, double *y, const enum fmt_type *format)
-{
-  if (lex_match_id (lexer, "LO") || lex_match_id (lexer, "LOWEST"))
-    *x = LOWEST;
-  else if (!parse_number (lexer, x, format))
-    return false;
-
-  if (lex_match_id (lexer, "THRU"))
-    {
-      if (lex_match_id (lexer, "HI") || lex_match_id (lexer, "HIGHEST"))
-        *y = HIGHEST;
-      else if (!parse_number (lexer, y, format))
-        return false;
-
-      if (*y < *x)
-        {
-          double t;
-          msg (SW, _("Low end of range (%g) is below high end (%g).  "
-                     "The range will be treated as reversed."),
-               *x, *y);
-          t = *x;
-          *x = *y;
-          *y = t;
-        }
-      else if (*x == *y)
-        msg (SW, _("Ends of range are equal (%g)."), *x);
-
-      return true;
-    }
-  else
-    {
-      if (*x == LOWEST)
-        {
-          msg (SE, _("LO or LOWEST must be part of a range."));
-          return false;
-        }
-      *y = *x;
-    }
-
-  return true;
-}
-
-/* Parses a number and stores it in *X.  Returns success.
-
-   Numeric values are always accepted.  If FORMAT is nonnull,
-   then string values are also accepted, and converted to numeric
-   values using *FORMAT. */
-static bool
-parse_number (struct lexer *lexer, double *x, const enum fmt_type *format)
-{
-  if (lex_is_number (lexer))
-    {
-      *x = lex_number (lexer);
-      lex_get (lexer);
-      return true;
-    }
-  else if (lex_token (lexer) == T_STRING && format != NULL)
-    {
-      union value v;
-      data_in (ds_ss (lex_tokstr (lexer)), LEGACY_NATIVE,
-               *format, 0, 0, 0, &v, 0);
-      lex_get (lexer);
-      *x = v.f;
-      if (*x == SYSMIS)
-        {
-          msg (SE, _("System-missing value is not valid here."));
-          return false;
-        }
-      return true;
-    }
-  else
-    {
-      if (format != NULL)
-        lex_error (lexer, _("expecting number or data string"));
-      else
-        lex_force_num (lexer);
-      return false;
-    }
-}
diff --git a/src/language/lexer/range-parser.h b/src/language/lexer/range-parser.h
deleted file mode 100644 (file)
index 8cff0e1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2005 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef RANGE_PRS_H
-#define RANGE_PRS_H 1
-
-#include <stdbool.h>
-
-struct lexer;
-enum fmt_type;
-bool parse_num_range (struct lexer *,
-                      double *x, double *y, const enum fmt_type *fmt);
-
-#endif /* range-prs.h */
diff --git a/src/language/lexer/value-parser.c b/src/language/lexer/value-parser.c
new file mode 100644 (file)
index 0000000..2cf9cf2
--- /dev/null
@@ -0,0 +1,145 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include "value-parser.h"
+#include <stdbool.h>
+#include <data/data-in.h>
+#include <libpspp/message.h>
+#include "lexer.h"
+#include <libpspp/str.h>
+#include <data/value.h>
+#include <data/format.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+static bool parse_number (struct lexer *, double *, const enum fmt_type *);
+
+/* Parses and stores a numeric value, or a range of the form "x
+   THRU y".  Open-ended ranges may be specified as "LO(WEST) THRU
+   y" or "x THRU HI(GHEST)".  Sets *X and *Y to the range or the
+   value and returns success.
+
+   Numeric values are always accepted.  If FORMAT is nonnull,
+   then string values are also accepted, and converted to numeric
+   values using *FORMAT. */
+bool
+parse_num_range (struct lexer *lexer,
+                 double *x, double *y, const enum fmt_type *format)
+{
+  if (lex_match_id (lexer, "LO") || lex_match_id (lexer, "LOWEST"))
+    *x = LOWEST;
+  else if (!parse_number (lexer, x, format))
+    return false;
+
+  if (lex_match_id (lexer, "THRU"))
+    {
+      if (lex_match_id (lexer, "HI") || lex_match_id (lexer, "HIGHEST"))
+        *y = HIGHEST;
+      else if (!parse_number (lexer, y, format))
+        return false;
+
+      if (*y < *x)
+        {
+          double t;
+          msg (SW, _("Low end of range (%g) is below high end (%g).  "
+                     "The range will be treated as reversed."),
+               *x, *y);
+          t = *x;
+          *x = *y;
+          *y = t;
+        }
+      else if (*x == *y)
+        msg (SW, _("Ends of range are equal (%g)."), *x);
+
+      return true;
+    }
+  else
+    {
+      if (*x == LOWEST)
+        {
+          msg (SE, _("LO or LOWEST must be part of a range."));
+          return false;
+        }
+      *y = *x;
+    }
+
+  return true;
+}
+
+/* Parses a number and stores it in *X.  Returns success.
+
+   Numeric values are always accepted.  If FORMAT is nonnull,
+   then string values are also accepted, and converted to numeric
+   values using *FORMAT. */
+static bool
+parse_number (struct lexer *lexer, double *x, const enum fmt_type *format)
+{
+  if (lex_is_number (lexer))
+    {
+      *x = lex_number (lexer);
+      lex_get (lexer);
+      return true;
+    }
+  else if (lex_token (lexer) == T_STRING && format != NULL)
+    {
+      union value v;
+      data_in (ds_ss (lex_tokstr (lexer)), LEGACY_NATIVE,
+               *format, 0, 0, 0, &v, 0);
+      lex_get (lexer);
+      *x = v.f;
+      if (*x == SYSMIS)
+        {
+          msg (SE, _("System-missing value is not valid here."));
+          return false;
+        }
+      return true;
+    }
+  else
+    {
+      if (format != NULL)
+        lex_error (lexer, _("expecting number or data string"));
+      else
+        lex_force_num (lexer);
+      return false;
+    }
+}
+
+/* Parses the current token from LEXER into value V, which must
+   already have been initialized with the specified WIDTH.
+   Returns true if successful, false otherwise. */
+bool
+parse_value (struct lexer *lexer, union value *v, int width)
+{
+  if (width == 0)
+    {
+      if (!lex_force_num (lexer))
+       return false;
+      v->f = lex_tokval (lexer);
+    }
+  else
+    {
+      if (!lex_force_string (lexer))
+       return false;
+      value_copy_str_rpad (v, width, ds_cstr (lex_tokstr (lexer)), ' ');
+    }
+
+  lex_get (lexer);
+
+  return true;
+}
diff --git a/src/language/lexer/value-parser.h b/src/language/lexer/value-parser.h
new file mode 100644 (file)
index 0000000..4f9004a
--- /dev/null
@@ -0,0 +1,29 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2005, 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef VALUE_PARSER_H
+#define VALUE_PARSER_H 1
+
+#include <stdbool.h>
+
+struct lexer;
+enum fmt_type;
+union value;
+bool parse_num_range (struct lexer *,
+                      double *x, double *y, const enum fmt_type *fmt);
+bool parse_value (struct lexer *, union value *, int width);
+
+#endif /* value-parser.h */
index a3f4cf8f522516d810ae29948a8402becd01c636..c0a6f47715acf6d6b69aba0a820f37905572f376 100644 (file)
@@ -32,6 +32,7 @@
 #include <language/command.h>
 #include <language/dictionary/split-file.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/value-parser.h>
 #include <libpspp/array.h>
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
@@ -126,8 +127,6 @@ struct t_test_proc
     union value g_value[2];     /* CMP_EQ only: Per-group indep var values. */
   };
 
-static int parse_value (struct lexer *, union value *, int width);
-
 /* Statistics Summary Box */
 struct ssbox
   {
@@ -421,29 +420,6 @@ tts_custom_pairs (struct lexer *lexer, struct dataset *ds,
   free (vars2);
   return 1;
 }
-
-/* Parses the current token (numeric or string, depending on type)
-   value v and returns success. */
-static int
-parse_value (struct lexer *lexer, union value *v, int width)
-{
-  if (width == 0)
-    {
-      if (!lex_force_num (lexer))
-       return 0;
-      v->f = lex_tokval (lexer);
-    }
-  else
-    {
-      if (!lex_force_string (lexer))
-       return 0;
-      value_copy_str_rpad (v, width, ds_cstr (lex_tokstr (lexer)), ' ');
-    }
-
-  lex_get (lexer);
-
-  return 1;
-}
 \f
 /* Implementation of the SSBOX object. */
 
index 6e234c4b23728fa9e1e886db9a9585e9fd5c5274..8ce2d12576697beb5562fc65fc4a03522ce2a9a0 100644 (file)
@@ -25,7 +25,7 @@
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
-#include <language/lexer/range-parser.h>
+#include <language/lexer/value-parser.h>
 #include <language/lexer/variable-parser.h>
 #include <libpspp/compiler.h>
 #include <libpspp/message.h>
index 57a742c96c16b6534dd23c205d39b2140441902a..60c8f408291b4076bc8f25ab630c47e4bf90b92d 100644 (file)
@@ -29,8 +29,8 @@
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/value-parser.h>
 #include <language/lexer/variable-parser.h>
-#include <language/lexer/range-parser.h>
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 #include <libpspp/message.h>