Changed all the licence notices in all the files.
[pspp-builds.git] / src / expressions / parse.c
index 2288d5277b6afb3e362ef00d979967219b09bc3e..ba790d08838a1cb30a3ac550f0926ee0983d5dbd 100644 (file)
@@ -14,8 +14,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "private.h"
@@ -56,6 +56,8 @@ static struct expression *finish_expression (union any_node *,
                                              struct expression *);
 static bool type_check (struct expression *, union any_node **,
                         enum expr_type expected_type);
+static union any_node *allocate_unary_variable (struct expression *,
+                                                struct variable *); 
 \f
 /* Public functions. */
 
@@ -66,7 +68,7 @@ static bool type_check (struct expression *, union any_node **,
    Returns the new expression if successful or a null pointer
    otherwise. */
 struct expression *
-expr_parse (struct dictionary *dict, atom_type type) 
+expr_parse (struct dictionary *dict, enum expr_type type) 
 {
   union any_node *n;
   struct expression *e;
@@ -267,13 +269,12 @@ type_check (struct expression *e,
 /* Considers whether *NODE may be coerced to type REQUIRED_TYPE.
    Returns true if possible, false if disallowed.
 
-   If DO_COERCION is zero, then *NODE is not modified and there
+   If DO_COERCION is false, then *NODE is not modified and there
    are no side effects.
 
-   Otherwise, DO_COERCION is nonzero.  In this case, we perform
-   the coercion if possible, possibly modifying *NODE.  If the
-   coercion is not possible then we free *NODE and set *NODE to
-   a null pointer.
+   If DO_COERCION is true, we perform the coercion if possible,
+   modifying *NODE if necessary.  If the coercion is not possible
+   then we free *NODE and set *NODE to a null pointer.
 
    This function's interface is somewhat awkward.  Use one of the
    wrapper functions type_coercion(), type_coercion_assert(), or
@@ -335,7 +336,8 @@ type_coercion_core (struct expression *e,
 
     case OP_ni_format:
       if ((*node)->type == OP_format
-          && check_input_specifier (&(*node)->format.f, 0))
+          && check_input_specifier (&(*node)->format.f, false)
+          && check_specifier_type (&(*node)->format.f, NUMERIC, false))
         {
           if (do_coercion)
             (*node)->type = OP_ni_format;
@@ -345,7 +347,8 @@ type_coercion_core (struct expression *e,
 
     case OP_no_format:
       if ((*node)->type == OP_format
-          && check_output_specifier (&(*node)->format.f, 0))
+          && check_output_specifier (&(*node)->format.f, false)
+          && check_specifier_type (&(*node)->format.f, NUMERIC, false))
         {
           if (do_coercion)
             (*node)->type = OP_no_format;
@@ -387,10 +390,13 @@ type_coercion_core (struct expression *e,
     }
 
   if (do_coercion) 
-    msg (SE, _("Type mismatch while applying %s operator: "
-               "cannot convert %s to %s."),
-         operator_name,
-         atom_type_name (actual_type), atom_type_name (required_type));
+    {
+      msg (SE, _("Type mismatch while applying %s operator: "
+                 "cannot convert %s to %s."),
+           operator_name,
+           atom_type_name (actual_type), atom_type_name (required_type));
+      *node = NULL;
+    }
   return false;
 }
 
@@ -402,7 +408,7 @@ type_coercion (struct expression *e,
                atom_type required_type, union any_node **node,
                const char *operator_name)
 {
-  return type_coercion_core (e, required_type, node, operator_name, 1);
+  return type_coercion_core (e, required_type, node, operator_name, true);
 }
 
 /* Coerces *NODE to type REQUIRED_TYPE.
@@ -411,7 +417,7 @@ static void
 type_coercion_assert (struct expression *e,
                       atom_type required_type, union any_node **node)
 {
-  int success = type_coercion_core (e, required_type, node, NULL, 1);
+  int success = type_coercion_core (e, required_type, node, NULL, true);
   assert (success);
 }
 
@@ -421,7 +427,7 @@ static bool
 is_coercible (atom_type required_type, union any_node *const *node)
 {
   return type_coercion_core (NULL, required_type,
-                             (union any_node **) node, NULL, 0);
+                             (union any_node **) node, NULL, false);
 }
 
 /* How to parse an operator. */
@@ -517,7 +523,7 @@ parse_binary_operators (struct expression *e, union any_node *node,
 
       /* Convert the left-hand side to type OPERAND_TYPE. */
       if (!type_coercion (e, operand_type, &node, operator->name))
-        return node;
+        return NULL;
 
       /* Parse the right-hand side and coerce to type
          OPERAND_TYPE. */
@@ -651,7 +657,7 @@ parse_add (struct expression *e)
   static const struct operator ops[] = 
     {
       { '+', OP_ADD, "addition (\"+\")" },
-      { '-', OP_SUB, "subtraction (\"-\")-" },
+      { '-', OP_SUB, "subtraction (\"-\")" },
     };
   
   return parse_binary_operators (e, parse_mul (e),
@@ -783,12 +789,7 @@ parse_primary (struct expression *e)
           /* It looks like a user variable.
              (It could be a format specifier, but we'll assume
              it's a variable unless proven otherwise. */
-          struct variable *v = parse_dict_variable (e->dict);
-          assert (v != NULL);
-          return expr_allocate_unary (e,
-                                      (v->type == NUMERIC
-                                       ? OP_NUM_VAR : OP_STR_VAR),
-                                      expr_allocate_variable (e, v));
+          return allocate_unary_variable (e, parse_dict_variable (e->dict));
         }
       else 
         {
@@ -803,7 +804,8 @@ parse_primary (struct expression *e)
         }
       break;
       
-    case T_NUM: 
+    case T_POS_NUM: 
+    case T_NEG_NUM: 
       {
         union any_node *node = expr_allocate_number (e, tokval);
         lex_get ();
@@ -863,7 +865,7 @@ parse_vector_element (struct expression *e)
 
   return expr_allocate_binary (e, (vector->var[0]->type == NUMERIC
                                    ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
-                               expr_allocate_vector (e, vector), element);
+                               element, expr_allocate_vector (e, vector));
 }
 \f
 /* Individual function parsing. */
@@ -1098,14 +1100,12 @@ no_match (const char *func_name,
     }
   else 
     {
-      ds_create (&s, _("Function invocation "));
+      ds_puts (&s, _("Function invocation "));
       put_invocation (&s, func_name, args, arg_cnt);
       ds_puts (&s, _(" does not match any known function.  Candidates are:"));
 
       for (f = first; f < last; f++)
-        {
-          ds_printf (&s, "\n%s", f->prototype);
-        }
+        ds_printf (&s, "\n%s", f->prototype);
     }
   ds_putc (&s, '.');
 
@@ -1159,7 +1159,7 @@ parse_function (struct expression *e)
               goto fail;
             for (i = 0; i < var_cnt; i++)
               add_arg (&args, &arg_cnt, &arg_cap,
-                       expr_allocate_variable (e, vars[i]));
+                       allocate_unary_variable (e, vars[i]));
             free (vars);
           }
         else
@@ -1422,3 +1422,13 @@ expr_allocate_format (struct expression *e, const struct fmt_spec *format)
   n->format.f = *format;
   return n;
 }
+
+/* Allocates a unary composite node that represents the value of
+   variable V in expression E. */
+static union any_node *
+allocate_unary_variable (struct expression *e, struct variable *v) 
+{
+  assert (v != NULL);
+  return expr_allocate_unary (e, v->type == NUMERIC ? OP_NUM_VAR : OP_STR_VAR,
+                              expr_allocate_variable (e, v));
+}