Added parser for the ROC command.
[pspp-builds.git] / src / language / stats / roc.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "roc.h"
20 #include <data/procedure.h>
21 #include <language/lexer/variable-parser.h>
22 #include <language/lexer/value-parser.h>
23 #include <language/lexer/lexer.h>
24
25 #include "gettext.h"
26 #define _(msgid) gettext (msgid)
27 #define N_(msgid) msgid
28
29 struct cmd_roc
30 {
31   size_t n_vars;
32   const struct variable **vars;
33
34   struct variable *state_var ;
35   union value state_value;
36
37   /* Plot the roc curve */
38   bool curve;
39   /* Plot the reference line */
40   bool reference;
41
42   double ci;
43
44   bool print_coords;
45   bool print_se;
46   bool bi_neg_exp; /* True iff the bi-negative exponential critieria
47                       should be used */
48   enum mv_class exclude;
49
50   bool invert ; /* True iff a smaller test result variable indicates
51                    a positive result */
52
53 };
54
55
56 int
57 cmd_roc (struct lexer *lexer, struct dataset *ds)
58 {
59   struct cmd_roc roc ;
60   const struct dictionary *dict = dataset_dict (ds);
61
62   roc.vars = NULL;
63   roc.n_vars = 0;
64   roc.print_se = false;
65   roc.print_coords = false;
66   roc.exclude = MV_ANY;
67   roc.curve = true;
68   roc.reference = false;
69   roc.ci = 95;
70   roc.bi_neg_exp = false;
71   roc.invert = false;
72
73   if (!parse_variables_const (lexer, dict, &roc.vars, &roc.n_vars,
74                               PV_APPEND | PV_NO_DUPLICATE | PV_NUMERIC))
75     return 2;
76
77   if ( ! lex_force_match (lexer, T_BY))
78     {
79       return 2;
80     }
81
82   roc.state_var = parse_variable (lexer, dict);
83
84   if ( !lex_force_match (lexer, '('))
85     {
86       return 2;
87     }
88
89   parse_value (lexer, &roc.state_value, var_get_width (roc.state_var));
90
91
92   if ( !lex_force_match (lexer, ')'))
93     {
94       return 2;
95     }
96
97
98   while (lex_token (lexer) != '.')
99     {
100       lex_match (lexer, '/');
101       if (lex_match_id (lexer, "MISSING"))
102         {
103           lex_match (lexer, '=');
104           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
105             {
106               if (lex_match_id (lexer, "INCLUDE"))
107                 {
108                   roc.exclude = MV_SYSTEM;
109                 }
110               else if (lex_match_id (lexer, "EXCLUDE"))
111                 {
112                   roc.exclude = MV_ANY;
113                 }
114               else
115                 {
116                   lex_error (lexer, NULL);
117                   return 2;
118                 }
119             }
120         }
121       else if (lex_match_id (lexer, "PLOT"))
122         {
123           lex_match (lexer, '=');
124           if (lex_match_id (lexer, "CURVE"))
125             {
126               roc.curve = true;
127               if (lex_match (lexer, '('))
128                 {
129                   roc.reference = true;
130                   lex_force_match_id (lexer, "REFERENCE");
131                   lex_force_match (lexer, ')');
132                 }
133             }
134           else if (lex_match_id (lexer, "NONE"))
135             {
136               roc.curve = false;
137             }
138           else
139             {
140               lex_error (lexer, NULL);
141               return 2;
142             }
143         }
144       else if (lex_match_id (lexer, "PRINT"))
145         {
146           lex_match (lexer, '=');
147           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
148             {
149               if (lex_match_id (lexer, "SE"))
150                 {
151                   roc.print_se = true;
152                 }
153               else if (lex_match_id (lexer, "COORDINATES"))
154                 {
155                   roc.print_coords = true;
156                 }
157               else
158                 {
159                   lex_error (lexer, NULL);
160                   return 2;
161                 }
162             }
163         }
164       else if (lex_match_id (lexer, "CRITERIA"))
165         {
166           lex_match (lexer, '=');
167           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
168             {
169               if (lex_match_id (lexer, "CUTOFF"))
170                 {
171                   lex_force_match (lexer, '(');
172                   if (lex_match_id (lexer, "INCLUDE"))
173                     {
174                       roc.exclude = MV_SYSTEM;
175                     }
176                   else if (lex_match_id (lexer, "EXCLUDE"))
177                     {
178                       roc.exclude = MV_USER | MV_SYSTEM;
179                     }
180                   else
181                     {
182                       lex_error (lexer, NULL);
183                       return 2;
184                     }
185                   lex_force_match (lexer, ')');
186                 }
187               else if (lex_match_id (lexer, "TESTPOS"))
188                 {
189                   lex_force_match (lexer, '(');
190                   if (lex_match_id (lexer, "LARGE"))
191                     {
192                       roc.invert = false;
193                     }
194                   else if (lex_match_id (lexer, "SMALL"))
195                     {
196                       roc.invert = true;
197                     }
198                   else
199                     {
200                       lex_error (lexer, NULL);
201                       return 2;
202                     }
203                   lex_force_match (lexer, ')');
204                 }
205               else if (lex_match_id (lexer, "CI"))
206                 {
207                   lex_force_match (lexer, '(');
208                   lex_force_num (lexer);
209                   roc.ci = lex_number (lexer);
210                   lex_get (lexer);
211                   lex_force_match (lexer, ')');
212                 }
213               else if (lex_match_id (lexer, "DISTRIBUTION"))
214                 {
215                   lex_force_match (lexer, '(');
216                   if (lex_match_id (lexer, "FREE"))
217                     {
218                       roc.bi_neg_exp = false;
219                     }
220                   else if (lex_match_id (lexer, "NEGEXPO"))
221                     {
222                       roc.bi_neg_exp = true;
223                     }
224                   else
225                     {
226                       lex_error (lexer, NULL);
227                       return 2;
228                     }
229                   lex_force_match (lexer, ')');
230                 }
231               else
232                 {
233                   lex_error (lexer, NULL);
234                   return 2;
235                 }
236             }
237         }
238       else
239         {
240           lex_error (lexer, NULL);
241           break;
242         }
243     }
244
245
246   return 1;
247 }
248