From 3e502cc3d9cd7a12c9fb3d74f7af0044cc451c83 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 11 Sep 2022 23:01:53 -0700 Subject: [PATCH] MATRIX DATA: Improve error messages. --- src/language/data-io/matrix-data.c | 43 +++++++++++++++++++-------- tests/language/data-io/matrix-data.at | 20 +++++++++---- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/language/data-io/matrix-data.c b/src/language/data-io/matrix-data.c index 56f691bf7c..83490d4db8 100644 --- a/src/language/data-io/matrix-data.c +++ b/src/language/data-io/matrix-data.c @@ -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; } diff --git a/tests/language/data-io/matrix-data.at b/tests/language/data-io/matrix-data.at index 1dd0812024..da4653d749 100644 --- a/tests/language/data-io/matrix-data.at +++ b/tests/language/data-io/matrix-data.at @@ -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. -- 2.30.2