X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flanguage%2Fstats%2Fmeans-parser.c;fp=src%2Flanguage%2Fstats%2Fmeans-parser.c;h=0cc0b1b3172ffaf40673de96087784b918151eed;hb=09e70bd965a78b9831d51e93270d24932ed00b5b;hp=6bbae8938579aea56b23d1e2be216b323b3a8601;hpb=a862727ca32a30e52acf9b8386fc468ec3570660;p=pspp diff --git a/src/language/stats/means-parser.c b/src/language/stats/means-parser.c index 6bbae89385..0cc0b1b317 100644 --- a/src/language/stats/means-parser.c +++ b/src/language/stats/means-parser.c @@ -73,52 +73,67 @@ static bool lex_is_variable (struct lexer *lexer, const struct dictionary *dict, int n) { - const char *tstr; - if (lex_next_token (lexer, n) != T_ID) + if (lex_next_token (lexer, n) != T_ID) return false; - tstr = lex_next_tokcstr (lexer, n); + const char *tstr = lex_next_tokcstr (lexer, n); + return dict_lookup_var (dict, tstr) != NULL; +} - if (NULL == dict_lookup_var (dict, tstr)) - return false; +static const struct cell_spec * +match_cell (struct lexer *lexer) +{ + for (size_t i = 0; i < n_MEANS_STATISTICS; ++i) + { + const struct cell_spec *cs = &cell_spec[i]; + if (lex_match_id (lexer, cs->keyword)) + return cs; + } + return NULL; +} - return true; +static void +add_statistic (struct means *means, int statistic) +{ + if (means->n_statistics >= means->allocated_statistics) + means->statistics = pool_2nrealloc (means->pool, means->statistics, + &means->allocated_statistics, + sizeof *means->statistics); + means->statistics[means->n_statistics++] = statistic; +} + +void +means_set_default_statistics (struct means *means) +{ + means->n_statistics = 0; + add_statistic (means, MEANS_MEAN); + add_statistic (means, MEANS_N); + add_statistic (means, MEANS_STDDEV); } bool means_parse (struct lexer *lexer, struct means *means) { - /* Optional TABLES = */ - if (lex_match_id (lexer, "TABLES")) - { - if (! lex_force_match (lexer, T_EQUALS)) - return false; - } + /* Optional TABLES=. */ + if (lex_match_id (lexer, "TABLES") && !lex_force_match (lexer, T_EQUALS)) + return false; - bool more_tables = true; /* Parse the "tables" */ - while (more_tables) + for (;;) { means->table = pool_realloc (means->pool, means->table, - (means->n_tables + 1) * sizeof (*means->table)); + (means->n_tables + 1) * sizeof *means->table); - if (! parse_means_table_syntax (lexer, means, - &means->table[means->n_tables])) - { - return false; - } - means->n_tables ++; + if (!parse_means_table_syntax (lexer, means, + &means->table[means->n_tables])) + return false; + means->n_tables++; /* Look ahead to see if there are more tables to be parsed */ - more_tables = false; - if (T_SLASH == lex_next_token (lexer, 0)) - { - if (lex_is_variable (lexer, means->dict, 1)) - { - more_tables = true; - lex_match (lexer, T_SLASH); - } - } + if (lex_next_token (lexer, 0) != T_SLASH + || !lex_is_variable (lexer, means->dict, 1)) + break; + lex_match (lexer, T_SLASH); } /* /MISSING subcommand */ @@ -128,43 +143,36 @@ means_parse (struct lexer *lexer, struct means *means) if (lex_match_id (lexer, "MISSING")) { - /* - If no MISSING subcommand is specified, each combination of - a dependent variable and categorical variables is handled - separately. - */ + /* If no MISSING subcommand is specified, each combination of a + dependent variable and categorical variables is handled + separately. */ lex_match (lexer, T_EQUALS); if (lex_match_id (lexer, "INCLUDE")) { - /* - Use the subcommand "/MISSING=INCLUDE" to include user-missing - values in the analysis. - */ + /* Use the subcommand "/MISSING=INCLUDE" to include user-missing + values in the analysis. */ means->ctrl_exclude = MV_SYSTEM; means->dep_exclude = MV_SYSTEM; } else if (lex_match_id (lexer, "DEPENDENT")) - /* - Use the command "/MISSING=DEPENDENT" to - include user-missing values for the categorical variables, - while excluding them for the dependent variables. - - Cases are dropped only when user-missing values - appear in dependent variables. User-missing - values for categorical variables are treated according to - their face value. - - Cases are ALWAYS dropped when System Missing values appear - in the categorical variables. - */ + /* Use the command "/MISSING=DEPENDENT" to include user-missing + values for the categorical variables, while excluding them for + the dependent variables. + + Cases are dropped only when user-missing values appear in + dependent variables. User-missing values for categorical + variables are treated according to their face value. + + Cases are ALWAYS dropped when System Missing values appear in + the categorical variables. */ { means->dep_exclude = MV_ANY; means->ctrl_exclude = MV_SYSTEM; } else { - lex_error (lexer, NULL); + lex_error_expecting (lexer, "INCLUDE", "DEPENDENT"); return false; } } @@ -174,63 +182,30 @@ means_parse (struct lexer *lexer, struct means *means) /* The default values become overwritten */ means->n_statistics = 0; - pool_free (means->pool, means->statistics); - means->statistics = 0; - while (lex_token (lexer) != T_ENDCMD - && lex_token (lexer) != T_SLASH) + while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH) { if (lex_match (lexer, T_ALL)) { - pool_free (means->pool, means->statistics); - means->statistics = pool_calloc (means->pool, - n_MEANS_STATISTICS, - sizeof (*means->statistics)); - means->n_statistics = n_MEANS_STATISTICS; - int i; - for (i = 0; i < n_MEANS_STATISTICS; ++i) - { - means->statistics[i] = i; - } + means->n_statistics = 0; + for (int i = 0; i < n_MEANS_STATISTICS; ++i) + add_statistic (means, i); } else if (lex_match_id (lexer, "NONE")) - { - means->n_statistics = 0; - pool_free (means->pool, means->statistics); - means->statistics = 0; - } + means->n_statistics = 0; else if (lex_match_id (lexer, "DEFAULT")) + means_set_default_statistics (means); + else { - pool_free (means->pool, means->statistics); - means->statistics = pool_calloc (means->pool, - 3, - sizeof *means->statistics); - means->statistics[0] = MEANS_MEAN; - means->statistics[1] = MEANS_N; - means->statistics[2] = MEANS_STDDEV; - } - else - { - int i; - for (i = 0; i < n_MEANS_STATISTICS; ++i) - { - const struct cell_spec *cs = cell_spec + i; - if (lex_match_id (lexer, cs->keyword)) - { - means->statistics - = pool_realloc (means->pool, - means->statistics, - (means->n_statistics + 1) - * sizeof (*means->statistics)); - - means->statistics[means->n_statistics] = i; - means->n_statistics++; - break; - } - } - - if (i >= n_MEANS_STATISTICS) + const struct cell_spec *cs = match_cell (lexer); + if (cs) + add_statistic (means, cs - cell_spec); + else { - lex_error (lexer, NULL); + const char *keywords[n_MEANS_STATISTICS]; + for (int i = 0; i < n_MEANS_STATISTICS; ++i) + keywords[i] = cell_spec[i].keyword; + lex_error_expecting_array (lexer, keywords, + n_MEANS_STATISTICS); return false; } } @@ -238,7 +213,7 @@ means_parse (struct lexer *lexer, struct means *means) } else { - lex_error (lexer, NULL); + lex_error_expecting (lexer, "MISSING", "CELLS"); return false; } }