From 92e42986429596633f71457a585b3266209822dd Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 5 Nov 2011 11:23:23 -0700 Subject: [PATCH] lexer: New function lex_error_expecting(). This centralizes some fairly common strings into lexer.c. --- src/language/data-io/get-data.c | 7 +-- src/language/data-io/get.c | 2 +- src/language/data-io/save-translate.c | 18 +++---- src/language/data-io/save.c | 8 +-- src/language/dictionary/attributes.c | 2 +- src/language/expressions/parse.c | 3 +- src/language/lexer/lexer.c | 75 ++++++++++++++++++++++++++- src/language/lexer/lexer.h | 2 + src/language/stats/aggregate.c | 2 +- src/language/utilities/include.c | 10 ++-- src/language/utilities/set.q | 2 +- tests/language/control/do-repeat.at | 2 +- tests/language/data-io/inpt-pgm.at | 2 +- 13 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/language/data-io/get-data.c b/src/language/data-io/get-data.c index 9b878c55..4274f959 100644 --- a/src/language/data-io/get-data.c +++ b/src/language/data-io/get-data.c @@ -35,6 +35,7 @@ #include "language/data-io/placement-parser.h" #include "language/lexer/format-parser.h" #include "language/lexer/lexer.h" +#include "libpspp/cast.h" #include "libpspp/i18n.h" #include "libpspp/message.h" @@ -345,7 +346,7 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) DP_DELIMITED, &has_type); else { - lex_error (lexer, _("expecting %s or %s"), "FIXED", "DELIMITED"); + lex_error_expecting (lexer, "FIXED", "DELIMITED", NULL_SENTINEL); goto error; } if (!ok) @@ -383,7 +384,7 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) } else { - lex_error (lexer, _("expecting %s or %s"), "LINE", "VARIABLES"); + lex_error_expecting (lexer, "LINE", "VARIABLES", NULL_SENTINEL); goto error; } } @@ -494,7 +495,7 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) break; else { - lex_error (lexer, _("expecting %s"), "VARIABLES"); + lex_error_expecting (lexer, "VARIABLES", NULL_SENTINEL); goto error; } } diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 0e542ef0..ea65b5c1 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -96,7 +96,7 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command type = PFM_TAPE; else { - lex_error (lexer, _("expecting %s or %s"), "COMM", "TAPE"); + lex_error_expecting (lexer, "COMM", "TAPE", NULL_SENTINEL); goto error; } } diff --git a/src/language/data-io/save-translate.c b/src/language/data-io/save-translate.c index f6487c57..cbed4b10 100644 --- a/src/language/data-io/save-translate.c +++ b/src/language/data-io/save-translate.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010, 2011 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 @@ -115,7 +115,7 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) type = TAB_FILE; else { - lex_error (lexer, _("expecting %s or %s"), "CSV", "TAB"); + lex_error_expecting (lexer, "CSV", "TAB", NULL_SENTINEL); goto error; } } @@ -132,7 +132,7 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) recode_user_missing = true; else { - lex_error (lexer, _("expecting %s or %s"), "IGNORE", "RECODE"); + lex_error_expecting (lexer, "IGNORE", "RECODE", NULL_SENTINEL); goto error; } } @@ -145,7 +145,7 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) use_value_labels = true; else { - lex_error (lexer, _("expecting %s or %s"), "VALUES", "LABELS"); + lex_error_expecting (lexer, "VALUES", "LABELS", NULL_SENTINEL); goto error; } } @@ -193,8 +193,8 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) decimal = ','; else { - lex_error (lexer, _("expecting %s or %s"), - "DOT", "COMMA"); + lex_error_expecting (lexer, "DOT", "COMMA", + NULL_SENTINEL); goto error; } } @@ -207,8 +207,8 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) use_print_formats = true; else { - lex_error (lexer, _("expecting %s or %s"), - "PLAIN", "VARIABLE"); + lex_error_expecting (lexer, "PLAIN", "VARIABLE", + NULL_SENTINEL); goto error; } } @@ -225,7 +225,7 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds) retain_unselected = false; else { - lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE"); + lex_error_expecting (lexer, "RETAIN", "DELETE", NULL_SENTINEL); goto error; } } diff --git a/src/language/data-io/save.c b/src/language/data-io/save.c index cf847361..66cdd452 100644 --- a/src/language/data-io/save.c +++ b/src/language/data-io/save.c @@ -213,8 +213,8 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, cw = true; else { - lex_error (lexer, _("expecting %s or %s"), - "READONLY", "WRITEABLE"); + lex_error_expecting (lexer, "READONLY", "WRITEABLE", + NULL_SENTINEL); goto error; } sysfile_opts.create_writeable = porfile_opts.create_writeable = cw; @@ -228,7 +228,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, *retain_unselected = false; else { - lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE"); + lex_error_expecting (lexer, "RETAIN", "DELETE", NULL_SENTINEL); goto error; } } @@ -256,7 +256,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, porfile_opts.type = PFM_TAPE; else { - lex_error (lexer, _("expecting %s or %s"), "COMM", "TAPE"); + lex_error_expecting (lexer, "COMM", "TAPE", NULL_SENTINEL); goto error; } } diff --git a/src/language/dictionary/attributes.c b/src/language/dictionary/attributes.c index c7598d1c..fc9cc9a5 100644 --- a/src/language/dictionary/attributes.c +++ b/src/language/dictionary/attributes.c @@ -197,7 +197,7 @@ parse_attributes (struct lexer *lexer, const char *dict_encoding, command = DELETE; else if (command == UNKNOWN) { - lex_error (lexer, _("expecting %s or %s"), "ATTRIBUTE=", "DELETE="); + lex_error_expecting (lexer, "ATTRIBUTE=", "DELETE=", NULL_SENTINEL); return CMD_FAILURE; } diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index ed5a0709..32c2e615 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -1268,8 +1268,7 @@ parse_function (struct lexer *lexer, struct expression *e) break; else if (!lex_match (lexer, T_COMMA)) { - lex_error (lexer, _("expecting `,' or `)' invoking %s function"), - first->name); + lex_error_expecting (lexer, ",", ")", NULL_SENTINEL); goto fail; } } diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 5f1cc4ba..a356b382 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -268,6 +268,75 @@ lex_next_error (struct lexer *lexer, int n0, int n1, const char *format, ...) va_end (args); } +/* Prints a syntax error message saying that OPTION0 or one of the other + strings following it, up to the first NULL, is expected. */ +void +lex_error_expecting (struct lexer *lexer, const char *option0, ...) +{ + enum { MAX_OPTIONS = 8 }; + const char *options[MAX_OPTIONS + 1]; + va_list args; + int n; + + va_start (args, option0); + options[0] = option0; + n = 0; + while (n + 1 < MAX_OPTIONS && options[n] != NULL) + options[++n] = va_arg (args, const char *); + va_end (args); + + switch (n) + { + case 0: + lex_error (lexer, NULL); + break; + + case 1: + lex_error (lexer, _("expecting %s"), options[0]); + break; + + case 2: + lex_error (lexer, _("expecting %s or %s"), options[0], options[1]); + break; + + case 3: + lex_error (lexer, _("expecting %s, %s, or %s"), options[0], options[1], + options[2]); + break; + + case 4: + lex_error (lexer, _("expecting %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3]); + break; + + case 5: + lex_error (lexer, _("expecting %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4]); + break; + + case 6: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5]); + break; + + case 7: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5], options[6]); + break; + + case 8: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5], options[6], options[7]); + break; + + default: + NOT_REACHED (); + } +} + /* Reports an error to the effect that subcommand SBC may only be specified once. */ void @@ -491,7 +560,7 @@ lex_force_match_id (struct lexer *lexer, const char *identifier) return true; else { - lex_error (lexer, _("expecting `%s'"), identifier); + lex_error_expecting (lexer, identifier, NULL_SENTINEL); return false; } } @@ -508,7 +577,9 @@ lex_force_match (struct lexer *lexer, enum token_type type) } else { - lex_error (lexer, _("expecting `%s'"), token_type_to_string (type)); + char *s = xasprintf ("`%s'", token_type_to_string (type)); + lex_error_expecting (lexer, s, NULL_SENTINEL); + free (s); return false; } } diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index 0a3e6c37..b0787e8f 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -155,6 +155,8 @@ void lex_next_error (struct lexer *, int n0, int n1, const char *, ...) PRINTF_FORMAT (4, 5); int lex_end_of_command (struct lexer *); +void lex_error_expecting (struct lexer *, const char *, ...) SENTINEL(0); + void lex_sbc_only_once (const char *); void lex_sbc_missing (struct lexer *, const char *); diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index fed76569..f4cbaac4 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -223,7 +223,7 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds) lex_match (lexer, T_EQUALS); if (!lex_match_id (lexer, "COLUMNWISE")) { - lex_error (lexer, _("expecting %s"), "COLUMNWISE"); + lex_error_expecting (lexer, "COLUMNWISE", NULL); goto error; } agr.missing = COLUMNWISE; diff --git a/src/language/utilities/include.c b/src/language/utilities/include.c index bcee162c..89da3b9b 100644 --- a/src/language/utilities/include.c +++ b/src/language/utilities/include.c @@ -106,8 +106,8 @@ do_insert (struct lexer *lexer, struct dataset *ds, enum variant variant) syntax_mode = LEX_SYNTAX_AUTO; else { - lex_error (lexer, _("expecting %s, %s, or %s after %s"), - "BATCH", "INTERACTIVE", "AUTO", "SYNTAX"); + lex_error_expecting (lexer, "BATCH", "INTERACTIVE", "AUTO", + NULL_SENTINEL); goto exit; } } @@ -124,8 +124,7 @@ do_insert (struct lexer *lexer, struct dataset *ds, enum variant variant) } else { - lex_error (lexer, _("expecting %s or %s after %s"), - "YES", "NO", "CD"); + lex_error_expecting (lexer, "YES", "NO", NULL_SENTINEL); goto exit; } } @@ -142,8 +141,7 @@ do_insert (struct lexer *lexer, struct dataset *ds, enum variant variant) } else { - lex_error (lexer, _("expecting %s or %s after %s"), - "CONTINUE", "STOP", "ERROR"); + lex_error_expecting (lexer, "CONTINUE", "STOP", NULL_SENTINEL); goto exit; } } diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index c538c8c4..8b892c7f 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -331,7 +331,7 @@ stc_custom_tnumbers (struct lexer *lexer, } else { - lex_error (lexer, _("expecting VALUES, LABELS or BOTH")); + lex_error_expecting (lexer, "VALUES", "LABELS", "BOTH", NULL_SENTINEL); return 0; } diff --git a/tests/language/control/do-repeat.at b/tests/language/control/do-repeat.at index 4421ba6b..75c0e77a 100644 --- a/tests/language/control/do-repeat.at +++ b/tests/language/control/do-repeat.at @@ -145,6 +145,6 @@ DATA LIST NOTABLE /x 1. DO REPEAT y = 1 TO 10. ]) AT_CHECK([pspp -O format=csv do-repeat.sps], [1], [dnl -error: DO REPEAT: Syntax error at end of input: expecting `END'. +error: DO REPEAT: Syntax error at end of input: expecting END. ]) AT_CLEANUP diff --git a/tests/language/data-io/inpt-pgm.at b/tests/language/data-io/inpt-pgm.at index f048d374..03f9a2a5 100644 --- a/tests/language/data-io/inpt-pgm.at +++ b/tests/language/data-io/inpt-pgm.at @@ -28,6 +28,6 @@ END INPUT PROGRAM. DESCRIPTIVES x. ]) AT_CHECK([pspp -O format=csv input-program.sps], [1], [dnl -error: DESCRIPTIVES: Syntax error at end of input: expecting `BEGIN'. +error: DESCRIPTIVES: Syntax error at end of input: expecting BEGIN. ]) AT_CLEANUP -- 2.30.2