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.
/* 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
#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>
#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"
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, ')'))
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
+++ /dev/null
-/* 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;
- }
-}
+++ /dev/null
-/* 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 */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
#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>
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
{
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. */
#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>
#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>