From: Ben Pfaff Date: Sat, 27 Aug 2022 20:58:39 +0000 (-0700) Subject: add errors for unimplemented features X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=981adc6169ffe7227de286f92f70edf684d37a2b add errors for unimplemented features --- diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 7d40ce1cd5..7c540e5288 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -290,7 +290,7 @@ static void lex_source_push_parse (struct lex_source *, struct lex_token *); static void lex_source_clear_parse (struct lex_source *); static bool lex_source_get_parse (struct lex_source *); -static void lex_source_error_valist (struct lex_source *, int n0, int n1, +static void lex_source_error_valist (struct lex_source *, int ofs0, int ofs1, const char *format, va_list) PRINTF_FORMAT (4, 0); static const struct lex_token *lex_source_next__ (const struct lex_source *, @@ -425,7 +425,7 @@ lex_error (struct lexer *lexer, const char *format, ...) va_list args; va_start (args, format); - lex_next_error_valist (lexer, 0, 0, format, args); + lex_ofs_error_valist (lexer, lex_ofs (lexer), lex_ofs (lexer), format, args); va_end (args); } @@ -434,18 +434,33 @@ lex_error (struct lexer *lexer, const char *format, ...) void lex_error_valist (struct lexer *lexer, const char *format, va_list args) { - lex_next_error_valist (lexer, 0, 0, format, args); + lex_ofs_error_valist (lexer, lex_ofs (lexer), lex_ofs (lexer), format, args); } -/* Prints a syntax error message containing the current token and - given message MESSAGE (if non-null). */ +/* Prints a syntax error message for the span of tokens N0 through N1, + inclusive, from the current token in LEXER, adding message MESSAGE (if + non-null). */ void lex_next_error (struct lexer *lexer, int n0, int n1, const char *format, ...) { va_list args; va_start (args, format); - lex_next_error_valist (lexer, n0, n1, format, args); + int ofs = lex_ofs (lexer); + lex_ofs_error_valist (lexer, n0 + ofs, n1 + ofs, format, args); + va_end (args); +} + +/* Prints a syntax error message for the span of tokens with offsets OFS0 + through OFS1, inclusive, within the current command in LEXER, adding message + MESSAGE (if non-null). */ +void +lex_ofs_error (struct lexer *lexer, int ofs0, int ofs1, const char *format, ...) +{ + va_list args; + + va_start (args, format); + lex_ofs_error_valist (lexer, ofs0, ofs1, format, args); va_end (args); } @@ -584,16 +599,17 @@ lex_spec_missing (struct lexer *lexer, const char *sbc, const char *spec) sbc, spec); } -/* Prints a syntax error message containing the current token and - given message MESSAGE (if non-null). */ +/* Prints a syntax error message for the span of tokens with offsets OFS0 + through OFS1, inclusive, within the current command in LEXER, adding message + MESSAGE (if non-null) with the given ARGS. */ void -lex_next_error_valist (struct lexer *lexer, int n0, int n1, - const char *format, va_list args) +lex_ofs_error_valist (struct lexer *lexer, int ofs0, int ofs1, + const char *format, va_list args) { struct lex_source *src = lex_source__ (lexer); if (src != NULL) - lex_source_error_valist (src, n0, n1, format, args); + lex_source_error_valist (src, ofs0, ofs1, format, args); else { struct string s; @@ -1644,11 +1660,11 @@ lex_token_location_rw (const struct lex_source *src, } static struct msg_location * -lex_source_get_location (const struct lex_source *src, int n0, int n1) +lex_source_get_location (const struct lex_source *src, int ofs0, int ofs1) { return lex_token_location_rw (src, - lex_source_next__ (src, n0), - lex_source_next__ (src, n1)); + lex_source_ofs__ (src, ofs0), + lex_source_ofs__ (src, ofs1)); } /* Returns the name of the syntax file from which the current command is drawn. @@ -1866,10 +1882,10 @@ lex_source_syntax__ (const struct lex_source *src, int ofs0, int ofs1) } static bool -lex_source_contains_macro_call (struct lex_source *src, int n0, int n1) +lex_source_contains_macro_call (struct lex_source *src, int ofs0, int ofs1) { - for (int i = n0; i <= n1; i++) - if (lex_source_next__ (src, i)->macro_rep) + for (int i = ofs0; i <= ofs1; i++) + if (lex_source_ofs__ (src, i)->macro_rep) return true; return false; } @@ -1884,13 +1900,13 @@ lex_source_contains_macro_call (struct lex_source *src, int n0, int n1) The caller must not modify or free the returned string. */ static struct substring -lex_source_get_macro_call (struct lex_source *src, int n0, int n1) +lex_source_get_macro_call (struct lex_source *src, int ofs0, int ofs1) { - if (!lex_source_contains_macro_call (src, n0, n1)) + if (!lex_source_contains_macro_call (src, ofs0, ofs1)) return ss_empty (); - const struct lex_token *token0 = lex_source_next__ (src, n0); - const struct lex_token *token1 = lex_source_next__ (src, MAX (n0, n1)); + const struct lex_token *token0 = lex_source_ofs__ (src, ofs0); + const struct lex_token *token1 = lex_source_ofs__ (src, MAX (ofs0, ofs1)); size_t start = token0->token_pos; size_t end = token1->token_pos + token1->token_len; @@ -1898,7 +1914,7 @@ lex_source_get_macro_call (struct lex_source *src, int n0, int n1) } static void -lex_source_error_valist (struct lex_source *src, int n0, int n1, +lex_source_error_valist (struct lex_source *src, int ofs0, int ofs1, const char *format, va_list args) { const struct lex_token *token; @@ -1906,14 +1922,13 @@ lex_source_error_valist (struct lex_source *src, int n0, int n1, ds_init_empty (&s); - token = lex_source_next__ (src, n0); + token = lex_source_ofs__ (src, ofs0); if (token->token.type == T_ENDCMD) ds_put_cstr (&s, _("Syntax error at end of command")); else { /* Get the syntax that caused the error. */ - char *raw_syntax = lex_source_syntax__ (src, n0 + src->parse_ofs, - n1 + src->parse_ofs); + char *raw_syntax = lex_source_syntax__ (src, ofs0, ofs1); char syntax[64]; str_ellipsize (ss_cstr (raw_syntax), syntax, sizeof syntax); free (raw_syntax); @@ -1921,7 +1936,7 @@ lex_source_error_valist (struct lex_source *src, int n0, int n1, /* Get the macro call(s) that expanded to the syntax that caused the error. */ char call[64]; - str_ellipsize (lex_source_get_macro_call (src, n0, n1), + str_ellipsize (lex_source_get_macro_call (src, ofs0, ofs1), call, sizeof call); if (syntax[0]) @@ -1955,7 +1970,7 @@ lex_source_error_valist (struct lex_source *src, int n0, int n1, *m = (struct msg) { .category = MSG_C_SYNTAX, .severity = MSG_S_ERROR, - .location = lex_source_get_location (src, n0, n1), + .location = lex_source_get_location (src, ofs0, ofs1), .text = ds_steal_cstr (&s), }; msg_emit (m); diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index bb9d6a954d..ed4711213a 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -178,6 +178,8 @@ const char *lex_get_encoding (const struct lexer *); void lex_error (struct lexer *, const char *, ...) PRINTF_FORMAT (2, 3); void lex_next_error (struct lexer *, int n0, int n1, const char *, ...) PRINTF_FORMAT (4, 5); +void lex_ofs_error (struct lexer *, int ofs0, int ofs1, const char *, ...) + PRINTF_FORMAT (4, 5); int lex_end_of_command (struct lexer *); void lex_error_expecting (struct lexer *, ...) SENTINEL(0); @@ -196,8 +198,8 @@ void lex_spec_missing (struct lexer *, const char *subcommand, void lex_error_valist (struct lexer *, const char *, va_list) PRINTF_FORMAT (2, 0); -void lex_next_error_valist (struct lexer *lexer, int n0, int n1, - const char *format, va_list) +void lex_ofs_error_valist (struct lexer *lexer, int ofs0, int ofs1, + const char *format, va_list) PRINTF_FORMAT (4, 0); /* Error handling. */ diff --git a/src/language/stats/ctables.c b/src/language/stats/ctables.c index 12f9958c3c..68d3e852ba 100644 --- a/src/language/stats/ctables.c +++ b/src/language/stats/ctables.c @@ -229,8 +229,6 @@ struct ctables_cell axes[PIVOT_N_AXES]; union ctables_summary *summaries; - - //char *name; }; struct ctables @@ -873,6 +871,15 @@ parse_ctables_summary_function (struct lexer *lexer, return false; struct substring name = lex_tokss (lexer); + if (ss_ends_with_case (name, ss_cstr (".LCL")) + || ss_ends_with_case (name, ss_cstr (".UCL")) + || ss_ends_with_case (name, ss_cstr (".SE"))) + { + lex_error (lexer, _("Support for LCL, UCL, and SE summary functions " + "is not yet implemented.")); + return false; + } + bool u = ss_match_byte (&name, 'U') || ss_match_byte (&name, 'u'); bool e = !u && (ss_match_byte (&name, 'E') || ss_match_byte (&name, 'e')); @@ -1235,6 +1242,13 @@ ctables_axis_parse_primary (struct ctables_axis_parse_ctx *ctx) if (!lex_force_id (ctx->lexer)) return NULL; + if (lex_tokcstr (ctx->lexer)[0] == '$') + { + lex_error (ctx->lexer, + _("Multiple response set support not implemented.")); + return NULL; + } + int start_ofs = lex_ofs (ctx->lexer); struct variable *var = parse_variable (ctx->lexer, ctx->dict); if (!var) @@ -2109,6 +2123,7 @@ ctables_table_parse_categories (struct lexer *lexer, struct dictionary *dict, } else if (!c->n_cats && lex_match_id (lexer, "KEY")) { + int start_ofs = lex_ofs (lexer) - 1; lex_match (lexer, T_EQUALS); if (lex_match_id (lexer, "VALUE")) cat.type = CCT_VALUE; @@ -2145,6 +2160,10 @@ ctables_table_parse_categories (struct lexer *lexer, struct dictionary *dict, bool UNUSED b = lex_force_match (lexer, T_LPAREN); goto error; } + + lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1, + _("Data-dependent sorting is not implemented.")); + goto error; } } else if (!c->n_cats && lex_match_id (lexer, "MISSING")) @@ -3183,7 +3202,6 @@ ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c, cell->sv = sv; cell->omit_areas = 0; cell->postcompute = false; - //struct string name = DS_EMPTY_INITIALIZER; for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++) { const struct ctables_nest *nest = s->nests[a]; @@ -3233,28 +3251,8 @@ ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c, cell->axes[a].cvs[i].category = cat; value_clone (&cell->axes[a].cvs[i].value, value, var_get_width (var)); - -#if 0 - if (i != nest->scale_idx) - { - if (!ds_is_empty (&name)) - ds_put_cstr (&name, ", "); - char *value_s = data_out (value, var_get_encoding (var), - var_get_print_format (var), - settings_get_fmt_settings ()); - if (cat->type == CCT_TOTAL - || cat->type == CCT_SUBTOTAL - || cat->type == CCT_POSTCOMPUTE) - ds_put_format (&name, "%s=total", var_get_name (var)); - else - ds_put_format (&name, "%s=%s", var_get_name (var), - value_s + strspn (value_s, " ")); - free (value_s); - } -#endif } } - //cell->name = ds_steal_cstr (&name); const struct ctables_nest *ss = s->nests[s->table->summary_axis]; const struct ctables_summary_spec_set *specs = &ss->specs[cell->sv]; @@ -4162,32 +4160,6 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t) struct ctables_cell_sort_aux aux = { .nest = nest, .a = a }; sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_3way, &aux); -#if 0 - if (a == PIVOT_AXIS_ROW) - { - size_t ids[N_CTATS]; - memset (ids, 0, sizeof ids); - for (size_t j = 0; j < n_sorted; j++) - { - struct ctables_cell *cell = sorted[j]; - for (enum ctables_area_type at = 0; at < N_CTATS; at++) - { - struct ctables_area *area = cell->areas[at]; - if (!area->sequence) - area->sequence = ++ids[at]; - } - } - } -#endif - -#if 0 - for (size_t j = 0; j < n_sorted; j++) - { - printf ("%s (%s): %f/%f = %.1f%%\n", sorted[j]->name, sorted[j]->contributes_to_areas ? "y" : "n", sorted[j]->summaries[0].count, sorted[j]->areas[CTAT_COL]->e_count, sorted[j]->summaries[0].count / sorted[j]->areas[CTAT_COL]->e_count * 100.0); - } - printf ("\n"); -#endif - struct ctables_level { enum ctables_level_type @@ -4847,24 +4819,6 @@ ctables_prepare_table (struct ctables_table *t) } free (items); -#if 0 - for (size_t j = 0; j < merged->n; j++) - printf ("%s\n", ctables_summary_function_name (merged->specs[j].function)); - - for (size_t j = 0; j < stack->n; j++) - { - const struct ctables_nest *nest = &stack->nests[j]; - for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++) - { - const struct ctables_summary_spec_set *specs = &nest->specs[sv]; - for (size_t k = 0; k < specs->n; k++) - printf ("(%s, %zu) ", ctables_summary_function_name (specs->specs[k].function), - specs->specs[k].axis_idx); - printf ("\n"); - } - } -#endif - size_t allocated_sum_vars = 0; enumerate_sum_vars (t->axes[t->summary_axis], &t->sum_vars, &t->n_sum_vars, &allocated_sum_vars); @@ -6483,6 +6437,7 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds) } else if (lex_match_id (lexer, "SIGTEST")) { + int start_ofs = lex_ofs (lexer) - 1; if (!t->chisq) { t->chisq = xmalloc (sizeof *t->chisq); @@ -6538,9 +6493,14 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds) } while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD); + + lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1, + _("Support for SIGTEST not yet implemented.")); + goto error; } else if (lex_match_id (lexer, "COMPARETEST")) { + int start_ofs = lex_ofs (lexer); if (!t->pairwise) { t->pairwise = xmalloc (sizeof *t->pairwise); @@ -6680,6 +6640,10 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds) } while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD); + + lex_ofs_error (lexer, start_ofs, lex_ofs (lexer) - 1, + _("Support for COMPARETEST not yet implemented.")); + goto error; } else { diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 45187ef12b..2a592b9064 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -758,6 +758,14 @@ ss_starts_with (struct substring ss, struct substring prefix) && !memcmp (ss.string, prefix.string, prefix.length)); } +/* Returns true if SS starts with PREFIX in any case, false otherwise. */ +bool +ss_starts_with_case (struct substring ss, struct substring prefix) +{ + return (ss.length >= prefix.length + && !memcasecmp (ss.string, prefix.string, prefix.length)); +} + /* Returns true if SS ends with SUFFIX, false otherwise. */ bool ss_ends_with (struct substring ss, struct substring suffix) @@ -767,6 +775,15 @@ ss_ends_with (struct substring ss, struct substring suffix) suffix.length)); } +/* Returns true if SS ends with SUFFIX in any case, false otherwise. */ +bool +ss_ends_with_case (struct substring ss, struct substring suffix) +{ + return (ss.length >= suffix.length + && !memcasecmp (&ss.string[ss.length - suffix.length], suffix.string, + suffix.length)); +} + /* Returns the number of contiguous bytes at the beginning of SS that are in SKIP_SET. */ size_t diff --git a/src/libpspp/str.h b/src/libpspp/str.h index 86ffddca32..c40915d939 100644 --- a/src/libpspp/str.h +++ b/src/libpspp/str.h @@ -133,7 +133,9 @@ int ss_at (struct substring, size_t idx); int ss_first (struct substring); int ss_last (struct substring); bool ss_starts_with (struct substring, struct substring prefix); +bool ss_starts_with_case (struct substring, struct substring prefix); bool ss_ends_with (struct substring, struct substring suffix); +bool ss_ends_with_case (struct substring, struct substring suffix); size_t ss_span (struct substring, struct substring skip_set); size_t ss_cspan (struct substring, struct substring stop_set); size_t ss_find_byte (struct substring, char); diff --git a/tests/language/stats/ctables.at b/tests/language/stats/ctables.at index 67d6db4b26..6885f935ea 100644 --- a/tests/language/stats/ctables.at +++ b/tests/language/stats/ctables.at @@ -1,11 +1,6 @@ AT_BANNER([CTABLES]) -dnl Features not yet tested: -dnl - Summary functions: -dnl * WEIGHT and adjustment weights. -dnl * details of missing value handling in summaries. -dnl -dnl Not for v1: +dnl Features not yet implemented: dnl - Multiple response sets dnl - MRSETS subcommand. dnl - CATEGORIES: Special case for explicit category specifications and multiple dichotomy sets. @@ -14,8 +9,6 @@ dnl - COMPARETEST dnl - Summary functions: dnl * .LCL and .UCL suffixes. dnl * .SE suffixes. -dnl - Summary functions: -dnl * )CILEVEL in summary label specification dnl - CATEGORIES: dnl * Data-dependent sorting. @@ -533,6 +526,15 @@ CTABLES /PCOMPUTE &x=EXPR(**). CTABLES /TABLE. CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT]. + +CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=PTILE(qn1, 50). + +CTABLES /TABLE $mrset. + +CTABLES /TABLE qn113 /SIGTEST TYPE=CHISQUARE. +CTABLES /TABLE qn113 /COMPARETEST TYPE=PROP. + +CTABLES /TABLE qn113 [COUNT.UCL]. ]]) AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [1], [[ctables.sps:2.76-2.78: error: CTABLES: Computed category &pc references a @@ -595,8 +597,8 @@ variable string. 8 | CTABLES /TABLE string /CATEGORIES VARIABLES=string [1]. | ^ -ctables.sps:10: error: CTABLES: ROWLABELS=OPPOSITE is not allowed with sorting -based on a summary function. +ctables.sps:10.74-10.86: error: CTABLES: Syntax error at `KEY=MEAN(qn1)': Data- +dependent sorting is not implemented. ctables.sps:12: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be moved to be categorical, but qnd1 is a scale variable. @@ -649,6 +651,21 @@ ctables.sps:23.33-23.37: note: CTABLES: This is a scale variable, so it always has a summary even if the syntax does not explicitly specify one. 23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT]. | ^~~~~ + +ctables.sps:25.46-25.63: error: CTABLES: Syntax error at `KEY=PTILE(qn1, 50)': +Data-dependent sorting is not implemented. + +ctables.sps:27.16-27.21: error: CTABLES: Syntax error at `$mrset': Multiple +response set support not implemented. + +ctables.sps:29.23-29.44: error: CTABLES: Syntax error at `SIGTEST +TYPE=CHISQUARE': Support for SIGTEST not yet implemented. + +ctables.sps:30.35-30.43: error: CTABLES: Syntax error at `TYPE=PROP': Support +for COMPARETEST not yet implemented. + +ctables.sps:32.23-32.31: error: CTABLES: Syntax error at `COUNT.UCL': Support +for LCL, UCL, and SE summary functions is not yet implemented. ]]) AT_CLEANUP