MATRIX DATA: Improve error messages.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 12 Sep 2022 06:01:53 +0000 (23:01 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 12 Sep 2022 06:01:53 +0000 (23:01 -0700)
src/language/data-io/matrix-data.c
tests/language/data-io/matrix-data.at

index 56f691bf7c577291a1310bdaddd58ca9ade4ecd6..83490d4db824fe67756d7c1fc824971bcb815003 100644 (file)
@@ -837,11 +837,13 @@ parse_matrix_data_variables (struct lexer *lexer)
 
   size_t n_names = 0;
   char **names = NULL;
+  int vars_start = lex_ofs (lexer);
   if (!parse_DATA_LIST_vars (lexer, dict, &names, &n_names, PV_NO_DUPLICATE))
     {
       dict_unref (dict);
       return NULL;
     }
+  int vars_end = lex_ofs (lexer) - 1;
 
   for (size_t i = 0; i < n_names; i++)
     if (!strcasecmp (names[i], "ROWTYPE_"))
@@ -858,7 +860,8 @@ parse_matrix_data_variables (struct lexer *lexer)
 
   if (dict_lookup_var (dict, "VARNAME_"))
     {
-      msg (SE, _("VARIABLES may not include VARNAME_."));
+      lex_ofs_error (lexer, vars_start, vars_end,
+                     _("VARIABLES may not include VARNAME_."));
       dict_unref (dict);
       return NULL;
     }
@@ -891,8 +894,9 @@ parse_matrix_data_subvars (struct lexer *lexer, struct dictionary *dict,
       bool *tv = &taken_vars[var_get_dict_index (v)];
       if (*tv)
         {
-          msg (SE, _("%s may not appear on both SPLIT and FACTORS."),
-               var_get_name (v));
+          lex_ofs_error (lexer, start_ofs, end_ofs,
+                         _("%s may not appear on both SPLIT and FACTORS."),
+                         var_get_name (v));
           goto error;
         }
       *tv = true;
@@ -914,9 +918,11 @@ error:
 int
 cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
 {
+  int input_vars_start = lex_ofs (lexer);
   struct dictionary *dict = parse_matrix_data_variables (lexer);
   if (!dict)
     return CMD_FAILURE;
+  int input_vars_end = lex_ofs (lexer) - 1;
 
   size_t n_input_vars = dict_get_n_vars (dict);
   struct variable **input_vars = xnmalloc (n_input_vars, sizeof *input_vars);
@@ -954,6 +960,8 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
     taken_vars[var_get_dict_index (rowtype)] = true;
 
   struct file_handle *fh = NULL;
+  int n_start = 0;
+  int n_end = 0;
   while (lex_token (lexer) != T_ENDCMD)
     {
       if (!lex_force_match (lexer, T_SLASH))
@@ -961,16 +969,19 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
 
       if (lex_match_id (lexer, "N"))
        {
+          n_start = lex_ofs (lexer) - 1;
          lex_match (lexer, T_EQUALS);
 
          if (!lex_force_int_range (lexer, "N", 0, INT_MAX))
            goto error;
 
          mf.n = lex_integer (lexer);
+          n_end = lex_ofs (lexer);
          lex_get (lexer);
        }
       else if (lex_match_id (lexer, "FORMAT"))
        {
+          int start_ofs = lex_ofs (lexer) - 1;
          lex_match (lexer, T_EQUALS);
 
          while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
@@ -995,6 +1006,15 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
                  goto error;
                }
            }
+          int end_ofs = lex_ofs (lexer) - 1;
+
+          if (mf.diagonal == NO_DIAGONAL && mf.triangle == FULL)
+            {
+              lex_ofs_error (lexer, start_ofs, end_ofs,
+                             _("FORMAT=FULL and FORMAT=NODIAGONAL are "
+                               "mutually exclusive."));
+              goto error;
+            }
        }
       else if (lex_match_id (lexer, "FILE"))
        {
@@ -1102,11 +1122,6 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
          goto error;
        }
     }
-  if (mf.diagonal == NO_DIAGONAL && mf.triangle == FULL)
-    {
-      msg (SE, _("FORMAT=FULL and FORMAT=NODIAGONAL are mutually exclusive."));
-      goto error;
-    }
   if (!mf.input_rowtype)
     {
       if (mf.cells < 0)
@@ -1141,7 +1156,8 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
       }
   if (!mf.n_cvars)
     {
-      msg (SE, _("At least one continuous variable is required."));
+      lex_ofs_error (lexer, input_vars_start, input_vars_end,
+                     _("At least one continuous variable is required."));
       goto error;
     }
   if (mf.input_rowtype)
@@ -1149,15 +1165,18 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
       for (size_t i = 0; i < mf.n_cvars; i++)
         if (mf.cvars[i] != input_vars[n_input_vars - mf.n_cvars + i])
           {
-            msg (SE, _("VARIABLES includes ROWTYPE_ but the continuous "
-                       "variables are not the last ones on VARIABLES."));
+            lex_ofs_error (lexer, input_vars_start, input_vars_end,
+                           _("VARIABLES includes ROWTYPE_ but the continuous "
+                             "variables are not the last ones on VARIABLES."));
             goto error;
           }
     }
   unsigned int rowtype_mask = mf.pooled_rowtype_mask | mf.factor_rowtype_mask;
   if (rowtype_mask & (1u << C_N) && mf.n >= 0)
     {
-      msg (SE, _("Cannot specify N on CONTENTS along with the N subcommand."));
+      lex_ofs_error (lexer, n_start, n_end,
+                     _("Cannot specify N on CONTENTS along with the "
+                       "N subcommand."));
       goto error;
     }
 
index 1dd0812024f087e0ae6d89f98f6fe6c36d9e8eb5..da4653d7492b6369e9f1151d2dc93ad3703765a4 100644 (file)
@@ -1185,7 +1185,9 @@ MATRIX DATA VARIABLES=v/CELLS=-1.
 MATRIX DATA VARIABLES=v/XYZZY.
 ])
 AT_CHECK([pspp matrix-data.sps -O format=csv], [1], [dnl
-matrix-data.sps:1: error: MATRIX DATA: VARIABLES may not include VARNAME_.
+"matrix-data.sps:1.23-1.36: error: MATRIX DATA: VARIABLES may not include VARNAME_.
+    1 | MATRIX DATA VARIABLES=var01 varname_.
+      |                       ^~~~~~~~~~~~~~"
 
 "matrix-data.sps:2.25: error: MATRIX DATA: Variable v appears twice in variable list.
     2 | MATRIX DATA VARIABLES=v v v.
@@ -1199,9 +1201,13 @@ matrix-data.sps:1: error: MATRIX DATA: VARIABLES may not include VARNAME_.
     4 | MATRIX DATA VARIABLES=rowtype_ v1 v2 v3/FACTORS=rowtype_.
       |                                                 ^~~~~~~~"
 
-matrix-data.sps:5: error: MATRIX DATA: v1 may not appear on both SPLIT and FACTORS.
+"matrix-data.sps:5.61-5.62: error: MATRIX DATA: v1 may not appear on both SPLIT and FACTORS.
+    5 | MATRIX DATA VARIABLES=rowtype_ s1 v1 v2 v3/SPLIT=v1/FACTORS=v1.
+      |                                                             ^~"
 
-matrix-data.sps:7: error: MATRIX DATA: FORMAT=FULL and FORMAT=NODIAGONAL are mutually exclusive.
+"matrix-data.sps:7.32-7.53: error: MATRIX DATA: FORMAT=FULL and FORMAT=NODIAGONAL are mutually exclusive.
+    7 | MATRIX DATA VARIABLES=v1 v2 v3/FORMAT=FULL NODIAGONAL.
+      |                                ^~~~~~~~~~~~~~~~~~~~~~"
 
 matrix-data.sps:8: error: MATRIX DATA: CELLS is required when factor variables are specified and VARIABLES does not include ROWTYPE_.
 
@@ -1209,9 +1215,13 @@ matrix-data.sps:9: warning: MATRIX DATA: CONTENTS was not specified and VARIABLE
 
 matrix-data.sps:12: error: MATRIX DATA: CELLS is required when factor variables are specified and VARIABLES does not include ROWTYPE_.
 
-matrix-data.sps:13: error: MATRIX DATA: VARIABLES includes ROWTYPE_ but the continuous variables are not the last ones on VARIABLES.
+"matrix-data.sps:13.13-13.39: error: MATRIX DATA: VARIABLES includes ROWTYPE_ but the continuous variables are not the last ones on VARIABLES.
+   13 | MATRIX DATA VARIABLES=v1 v2 v3 ROWTYPE_.
+      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~"
 
-matrix-data.sps:14: error: MATRIX DATA: Cannot specify N on CONTENTS along with the N subcommand.
+"matrix-data.sps:14.43-14.45: error: MATRIX DATA: Cannot specify N on CONTENTS along with the N subcommand.
+   14 | MATRIX DATA VARIABLES=v1 v2 v3/CONTENTS=N/N=5.
+      |                                           ^~~"
 
 "matrix-data.sps:15.35-15.39: error: MATRIX DATA: Syntax error expecting one of the following: CORR, COV, MAT, N_MATRIX, PROX, COUNT, DFE, MEAN, MSE, STDDEV, N, N_SCALAR, N_VECTOR, SD.
    15 | MATRIX DATA VARIABLES=v1/CONTENTS=XYZZY.