From: Ben Pfaff Date: Sun, 11 Sep 2022 01:11:18 +0000 (-0700) Subject: Improve error messages for missing subcommands. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4e3578b2c8ce537de5516af55a62b84ebf2b744;p=pspp Improve error messages for missing subcommands. --- diff --git a/src/language/control/loop.c b/src/language/control/loop.c index 13af822546..5c8cb14f09 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -223,7 +223,7 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer, } if (loop->last_expr == NULL) { - lex_sbc_missing ("TO"); + lex_sbc_missing (lexer, "TO"); return false; } diff --git a/src/language/data-io/combine-files.c b/src/language/data-io/combine-files.c index 9f39cad775..d0e08b5fd0 100644 --- a/src/language/data-io/combine-files.c +++ b/src/language/data-io/combine-files.c @@ -380,7 +380,7 @@ combine_files (enum comb_command_type command, { if (command == COMB_UPDATE) { - lex_sbc_missing ("BY"); + lex_sbc_missing (lexer, "BY"); goto error; } if (n_tables) diff --git a/src/language/data-io/file-handle.c b/src/language/data-io/file-handle.c index 01c56de196..01d707c0b9 100644 --- a/src/language/data-io/file-handle.c +++ b/src/language/data-io/file-handle.c @@ -202,7 +202,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED) struct fh_properties properties = *fh_default_properties (); if (file_name == NULL) { - lex_sbc_missing ("NAME"); + lex_sbc_missing (lexer, "NAME"); goto exit; } diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index e1bad76b93..cb1789aa37 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -119,7 +119,7 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, if (fh == NULL) { - lex_sbc_missing ("FILE"); + lex_sbc_missing (lexer, "FILE"); goto error; } diff --git a/src/language/data-io/save-translate.c b/src/language/data-io/save-translate.c index 3b68367997..c157701e6c 100644 --- a/src/language/data-io/save-translate.c +++ b/src/language/data-io/save-translate.c @@ -236,12 +236,12 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) if (type == 0) { - lex_sbc_missing ("TYPE"); + lex_sbc_missing (lexer, "TYPE"); goto error; } else if (handle == NULL) { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (lexer, "OUTFILE"); goto error; } else if (!replace && fn_exists (handle)) diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 4ba4ddd4e0..6ff0f9072d 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -144,7 +144,7 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds) if (h == NULL) { - lex_sbc_missing ("FILE"); + lex_sbc_missing (lexer, "FILE"); goto error; } diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 9a67f96922..cdfc848360 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -628,9 +628,10 @@ lex_sbc_only_once (struct lexer *lexer, const char *sbc) command has been parsed, and so lex_error() would always report "Syntax error at end of command", which does not help the user find the error. */ void -lex_sbc_missing (const char *sbc) +lex_sbc_missing (struct lexer *lexer, const char *sbc) { - msg (SE, _("Required subcommand %s was not specified."), sbc); + lex_ofs_error (lexer, 0, lex_max_ofs (lexer), + _("Required subcommand %s was not specified."), sbc); } /* Reports an error to the effect that specification SPEC may only be specified @@ -1474,6 +1475,25 @@ lex_ofs (const struct lexer *lexer) return src ? src->parse_ofs : 0; } +/* Returns the offset of the last token in the current command. */ +int +lex_max_ofs (const struct lexer *lexer) +{ + struct lex_source *src = lex_source__ (lexer); + if (!src) + return 0; + + int ofs = MAX (1, src->n_parse) - 1; + for (;;) + { + enum token_type type = lex_source_ofs__ (src, ofs)->token.type; + if (type == T_ENDCMD || type == T_STOP) + return ofs; + + ofs++; + } +} + /* Returns the token within LEXER's current command with offset OFS. Use lex_ofs() to find out the offset of the current token. */ const struct token * diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index c00f70646d..027339f96e 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -159,6 +159,7 @@ struct substring lex_next_tokss (const struct lexer *, int n); /* Looking at the current command, including lookahead and lookbehind. */ int lex_ofs (const struct lexer *); +int lex_max_ofs (const struct lexer *); const struct token *lex_ofs_token (const struct lexer *, int ofs); struct msg_location *lex_ofs_location (const struct lexer *, int ofs0, int ofs1); struct msg_point lex_ofs_start_point (const struct lexer *, int ofs); @@ -202,7 +203,7 @@ void lex_error_expecting_valist (struct lexer *, va_list); void lex_error_expecting_array (struct lexer *, const char **, size_t n); void lex_sbc_only_once (struct lexer *, const char *); -void lex_sbc_missing (const char *); +void lex_sbc_missing (struct lexer *, const char *); void lex_spec_only_once (struct lexer *, const char *subcommand, const char *specification); diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index 7c8d6519d1..01d4480787 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -6331,7 +6331,7 @@ matrix_save_parse (struct matrix_state *s) fh = fh_ref (s->prev_save_file); else { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } } @@ -6596,7 +6596,7 @@ matrix_read_parse (struct matrix_state *s) if (!read->c1) { - lex_sbc_missing ("FIELD"); + lex_sbc_missing (s->lexer, "FIELD"); goto error; } @@ -6615,7 +6615,7 @@ matrix_read_parse (struct matrix_state *s) fh = fh_ref (s->prev_read_file); else { - lex_sbc_missing ("FILE"); + lex_sbc_missing (s->lexer, "FILE"); goto error; } } @@ -7172,7 +7172,7 @@ matrix_write_parse (struct matrix_state *s) if (!write->c1) { - lex_sbc_missing ("FIELD"); + lex_sbc_missing (s->lexer, "FIELD"); goto error; } @@ -7182,7 +7182,7 @@ matrix_write_parse (struct matrix_state *s) fh = fh_ref (s->prev_write_file); else { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } } @@ -7896,7 +7896,7 @@ matrix_msave_parse (struct matrix_state *s) } if (!msave->rowtype) { - lex_sbc_missing ("TYPE"); + lex_sbc_missing (s->lexer, "TYPE"); goto error; } @@ -7914,7 +7914,7 @@ matrix_msave_parse (struct matrix_state *s) } if (!common->outfile) { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (s->lexer, "OUTFILE"); goto error; } common->location = lex_ofs_location (s->lexer, start_ofs, diff --git a/src/language/stats/t-test-parser.c b/src/language/stats/t-test-parser.c index 84759d8d10..cc6e35edb9 100644 --- a/src/language/stats/t-test-parser.c +++ b/src/language/stats/t-test-parser.c @@ -316,7 +316,7 @@ cmd_t_test (struct lexer *lexer, struct dataset *ds) if (tt.n_vars == 0 && tt.mode != MODE_PAIRED) { - lex_sbc_missing ("VARIABLES"); + lex_sbc_missing (lexer, "VARIABLES"); goto exit; } diff --git a/tests/language/control/loop.at b/tests/language/control/loop.at index 7f1f6e3b32..37125d9399 100644 --- a/tests/language/control/loop.at +++ b/tests/language/control/loop.at @@ -338,7 +338,9 @@ loop.sps:19.21-19.22: error: LOOP: Subcommand BY may only be specified once. 19 | LOOP A=1 BY 5 TO 10 BY !. | ^~ -loop.sps:21: error: LOOP: Required subcommand TO was not specified. +loop.sps:21.1-21.9: error: LOOP: Required subcommand TO was not specified. + 21 | LOOP A=1. + | ^~~~~~~~~ loop.sps:23.6: error: LOOP: Syntax error. 23 | LOOP !. diff --git a/tests/language/stats/matrix.at b/tests/language/stats/matrix.at index a152cbf009..c3cb334650 100644 --- a/tests/language/stats/matrix.at +++ b/tests/language/stats/matrix.at @@ -3388,7 +3388,9 @@ or FORMAT. 17 | READ x/!. | ^ -matrix.sps:18: error: READ: Required subcommand FIELD was not specified. +matrix.sps:18.1-18.7: error: READ: Required subcommand FIELD was not specified. + 18 | READ x. + | ^~~~~~~ matrix.sps:19: error: READ: SIZE is required for reading data into a full matrix (as opposed to a submatrix). @@ -3397,7 +3399,9 @@ matrix.sps:19.6: note: READ: This expression designates a full matrix. 19 | READ x/FIELD=1 TO 10. | ^ -matrix.sps:20: error: READ: Required subcommand FILE was not specified. +matrix.sps:20.1-20.32: error: READ: Required subcommand FILE was not specified. + 20 | READ x/FIELD=1 TO 10/SIZE={1,2}. + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ matrix.sps:21: error: READ: 15 repetitions cannot fit in record width 10. @@ -3602,9 +3606,15 @@ HOLD, or FORMAT. 14 | WRITE 1/!. | ^ -matrix.sps:15: error: WRITE: Required subcommand FIELD was not specified. +matrix.sps:15.1-15.8: error: WRITE: Required subcommand FIELD was not +specified. + 15 | WRITE 1. + | ^~~~~~~~ -matrix.sps:16: error: WRITE: Required subcommand OUTFILE was not specified. +matrix.sps:16.1-16.22: error: WRITE: Required subcommand OUTFILE was not +specified. + 16 | WRITE 1/FIELD=1 TO 10. + | ^~~~~~~~~~~~~~~~~~~~~~ matrix.sps:17.51-17.55: note: WRITE: This syntax designates the number of repetitions. @@ -4004,7 +4014,9 @@ or STRINGS. 6 | SAVE 1/!. | ^ -matrix.sps:7: error: SAVE: Required subcommand OUTFILE was not specified. +matrix.sps:7.1-7.7: error: SAVE: Required subcommand OUTFILE was not specified. + 7 | SAVE 1. + | ^~~~~~~ matrix.sps:8: warning: SAVE: VARIABLES and NAMES both specified; ignoring NAMES. @@ -4774,7 +4786,9 @@ FNAMES, SNAMES, SPLIT, or FACTOR. 10 | MSAVE 1/!. | ^ -matrix.sps:11: error: MSAVE: Required subcommand TYPE was not specified. +matrix.sps:11.1-11.8: error: MSAVE: Required subcommand TYPE was not specified. + 11 | MSAVE 1. + | ^~~~~~~~ matrix.sps:12.25: error: MSAVE: FNAMES requires FACTOR. 12 | MSAVE 1/TYPE=COV/FNAMES=x. @@ -4784,7 +4798,10 @@ matrix.sps:13.25: error: MSAVE: SNAMES requires SPLIT. 13 | MSAVE 1/TYPE=COV/SNAMES=x. | ^ -matrix.sps:14: error: MSAVE: Required subcommand OUTFILE was not specified. +matrix.sps:14.1-14.17: error: MSAVE: Required subcommand OUTFILE was not +specified. + 14 | MSAVE 1/TYPE=COV. + | ^~~~~~~~~~~~~~~~~ matrix.sps:20: error: MSAVE: OUTFILE must name the same file on each MSAVE within a single MATRIX command. diff --git a/tests/language/stats/t-test.at b/tests/language/stats/t-test.at index 7b36fb4aae..bf1b293603 100644 --- a/tests/language/stats/t-test.at +++ b/tests/language/stats/t-test.at @@ -729,9 +729,13 @@ T-TEST /testval=2.0 . T-TEST /groups=id(3) . ]) AT_CHECK([pspp -O format=csv t-test.sps], [1], [dnl -t-test.sps:11: error: T-TEST: Required subcommand VARIABLES was not specified. +"t-test.sps:11.1-11.21: error: T-TEST: Required subcommand VARIABLES was not specified. + 11 | T-TEST /testval=2.0 . + | ^~~~~~~~~~~~~~~~~~~~~" -t-test.sps:12: error: T-TEST: Required subcommand VARIABLES was not specified. +"t-test.sps:12.1-12.22: error: T-TEST: Required subcommand VARIABLES was not specified. + 12 | T-TEST /groups=id(3) . + | ^~~~~~~~~~~~~~~~~~~~~~" ]) AT_CLEANUP