41 |
vector element. */ |
vector element. */ |
42 |
static struct lvalue *lvalue_parse (void); |
static struct lvalue *lvalue_parse (void); |
43 |
static int lvalue_get_type (const struct lvalue *); |
static int lvalue_get_type (const struct lvalue *); |
44 |
static int lvalue_is_vector (const struct lvalue *); |
static bool lvalue_is_vector (const struct lvalue *); |
45 |
static void lvalue_finalize (struct lvalue *, |
static void lvalue_finalize (struct lvalue *, |
46 |
struct compute_trns *); |
struct compute_trns *); |
47 |
static void lvalue_destroy (struct lvalue *); |
static void lvalue_destroy (struct lvalue *); |
49 |
/* COMPUTE and IF transformation. */ |
/* COMPUTE and IF transformation. */ |
50 |
struct compute_trns |
struct compute_trns |
51 |
{ |
{ |
|
struct trns_header h; |
|
|
|
|
52 |
/* Test expression (IF only). */ |
/* Test expression (IF only). */ |
53 |
struct expression *test; /* Test expression. */ |
struct expression *test; /* Test expression. */ |
54 |
|
|
65 |
struct expression *rvalue; /* Rvalue expression. */ |
struct expression *rvalue; /* Rvalue expression. */ |
66 |
}; |
}; |
67 |
|
|
68 |
static int parse_rvalue_expression (struct compute_trns *, |
static struct expression *parse_rvalue (const struct lvalue *); |
|
const struct lvalue *); |
|
69 |
static struct compute_trns *compute_trns_create (void); |
static struct compute_trns *compute_trns_create (void); |
70 |
static void compute_trns_free (struct trns_header *); |
static trns_proc_func *get_proc_func (const struct lvalue *); |
71 |
|
static trns_free_func compute_trns_free; |
72 |
|
|
73 |
/* COMPUTE. */ |
/* COMPUTE. */ |
74 |
|
|
78 |
struct lvalue *lvalue = NULL; |
struct lvalue *lvalue = NULL; |
79 |
struct compute_trns *compute = NULL; |
struct compute_trns *compute = NULL; |
80 |
|
|
81 |
|
compute = compute_trns_create (); |
82 |
|
|
83 |
lvalue = lvalue_parse (); |
lvalue = lvalue_parse (); |
84 |
if (lvalue == NULL) |
if (lvalue == NULL) |
85 |
goto fail; |
goto fail; |
86 |
|
|
87 |
compute = compute_trns_create (); |
if (!lex_force_match ('=')) |
88 |
|
goto fail; |
89 |
if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue)) |
compute->rvalue = parse_rvalue (lvalue); |
90 |
|
if (compute->rvalue == NULL) |
91 |
goto fail; |
goto fail; |
92 |
|
|
93 |
lvalue_finalize (lvalue, compute); |
add_transformation (get_proc_func (lvalue), compute_trns_free, compute); |
94 |
|
|
95 |
add_transformation (&compute->h); |
lvalue_finalize (lvalue, compute); |
96 |
|
|
97 |
return CMD_SUCCESS; |
return lex_end_of_command (); |
98 |
|
|
99 |
fail: |
fail: |
100 |
lvalue_destroy (lvalue); |
lvalue_destroy (lvalue); |
101 |
if (compute != NULL) |
compute_trns_free (compute); |
|
{ |
|
|
compute_trns_free (&compute->h); |
|
|
free (compute); |
|
|
} |
|
102 |
return CMD_FAILURE; |
return CMD_FAILURE; |
103 |
} |
} |
104 |
|
|
106 |
|
|
107 |
/* Handle COMPUTE or IF with numeric target variable. */ |
/* Handle COMPUTE or IF with numeric target variable. */ |
108 |
static int |
static int |
109 |
compute_num (struct trns_header *compute_, struct ccase *c, |
compute_num (void *compute_, struct ccase *c, int case_num) |
|
int case_num) |
|
110 |
{ |
{ |
111 |
struct compute_trns *compute = (struct compute_trns *) compute_; |
struct compute_trns *compute = compute_; |
112 |
|
|
113 |
if (compute->test == NULL |
if (compute->test == NULL |
114 |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
121 |
/* Handle COMPUTE or IF with numeric vector element target |
/* Handle COMPUTE or IF with numeric vector element target |
122 |
variable. */ |
variable. */ |
123 |
static int |
static int |
124 |
compute_num_vec (struct trns_header *compute_, struct ccase *c, |
compute_num_vec (void *compute_, struct ccase *c, int case_num) |
|
int case_num) |
|
125 |
{ |
{ |
126 |
struct compute_trns *compute = (struct compute_trns *) compute_; |
struct compute_trns *compute = compute_; |
127 |
|
|
128 |
if (compute->test == NULL |
if (compute->test == NULL |
129 |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
153 |
|
|
154 |
/* Handle COMPUTE or IF with string target variable. */ |
/* Handle COMPUTE or IF with string target variable. */ |
155 |
static int |
static int |
156 |
compute_str (struct trns_header *compute_, struct ccase *c, |
compute_str (void *compute_, struct ccase *c, int case_num) |
|
int case_num) |
|
157 |
{ |
{ |
158 |
struct compute_trns *compute = (struct compute_trns *) compute_; |
struct compute_trns *compute = compute_; |
159 |
|
|
160 |
if (compute->test == NULL |
if (compute->test == NULL |
161 |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
168 |
/* Handle COMPUTE or IF with string vector element target |
/* Handle COMPUTE or IF with string vector element target |
169 |
variable. */ |
variable. */ |
170 |
static int |
static int |
171 |
compute_str_vec (struct trns_header *compute_, struct ccase *c, |
compute_str_vec (void *compute_, struct ccase *c, int case_num) |
|
int case_num) |
|
172 |
{ |
{ |
173 |
struct compute_trns *compute = (struct compute_trns *) compute_; |
struct compute_trns *compute = compute_; |
174 |
|
|
175 |
if (compute->test == NULL |
if (compute->test == NULL |
176 |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
|| expr_evaluate_num (compute->test, c, case_num) == 1.0) |
225 |
goto fail; |
goto fail; |
226 |
|
|
227 |
/* Rvalue expression. */ |
/* Rvalue expression. */ |
228 |
if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue)) |
if (!lex_force_match ('=')) |
229 |
|
goto fail; |
230 |
|
compute->rvalue = parse_rvalue (lvalue); |
231 |
|
if (compute->rvalue == NULL) |
232 |
goto fail; |
goto fail; |
233 |
|
|
234 |
lvalue_finalize (lvalue, compute); |
add_transformation (get_proc_func (lvalue), compute_trns_free, compute); |
235 |
|
|
236 |
add_transformation (&compute->h); |
lvalue_finalize (lvalue, compute); |
237 |
|
|
238 |
return CMD_SUCCESS; |
return lex_end_of_command (); |
239 |
|
|
240 |
fail: |
fail: |
241 |
lvalue_destroy (lvalue); |
lvalue_destroy (lvalue); |
242 |
if (compute != NULL) |
compute_trns_free (compute); |
|
{ |
|
|
compute_trns_free (&compute->h); |
|
|
free (compute); |
|
|
} |
|
243 |
return CMD_FAILURE; |
return CMD_FAILURE; |
244 |
} |
} |
245 |
|
|
246 |
/* Code common to COMPUTE and IF. */ |
/* Code common to COMPUTE and IF. */ |
247 |
|
|
248 |
/* Checks for type mismatches on transformation C. Also checks for |
static trns_proc_func * |
249 |
command terminator, sets the case-handling proc from the array |
get_proc_func (const struct lvalue *lvalue) |
|
passed. */ |
|
|
static int |
|
|
parse_rvalue_expression (struct compute_trns *compute, |
|
|
const struct lvalue *lvalue) |
|
250 |
{ |
{ |
251 |
int type = lvalue_get_type (lvalue); |
bool is_numeric = lvalue_get_type (lvalue) == NUMERIC; |
252 |
int vector = lvalue_is_vector (lvalue); |
bool is_vector = lvalue_is_vector (lvalue); |
253 |
|
|
254 |
assert (type == NUMERIC || type == ALPHA); |
return (is_numeric |
255 |
|
? (is_vector ? compute_num_vec : compute_num) |
256 |
compute->rvalue = expr_parse (default_dict, |
: (is_vector ? compute_str_vec : compute_str)); |
257 |
type == ALPHA ? EXPR_STRING : EXPR_NUMBER); |
} |
|
if (compute->rvalue == NULL) |
|
|
return 0; |
|
258 |
|
|
259 |
if (type == NUMERIC) |
/* Parses and returns an rvalue expression of the same type as |
260 |
compute->h.proc = vector ? compute_num_vec : compute_num; |
LVALUE, or a null pointer on failure. */ |
261 |
else |
static struct expression * |
262 |
compute->h.proc = vector ? compute_str_vec : compute_str; |
parse_rvalue (const struct lvalue *lvalue) |
263 |
|
{ |
264 |
|
bool is_numeric = lvalue_get_type (lvalue) == NUMERIC; |
265 |
|
|
266 |
if (token != '.') |
return expr_parse (default_dict, is_numeric ? EXPR_NUMBER : EXPR_STRING); |
|
{ |
|
|
lex_error (_("expecting end of command")); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
return 1; |
|
267 |
} |
} |
268 |
|
|
269 |
/* Returns a new struct compute_trns after initializing its fields. */ |
/* Returns a new struct compute_trns after initializing its fields. */ |
271 |
compute_trns_create (void) |
compute_trns_create (void) |
272 |
{ |
{ |
273 |
struct compute_trns *compute = xmalloc (sizeof *compute); |
struct compute_trns *compute = xmalloc (sizeof *compute); |
|
compute->h.proc = NULL; |
|
|
compute->h.free = compute_trns_free; |
|
274 |
compute->test = NULL; |
compute->test = NULL; |
275 |
compute->variable = NULL; |
compute->variable = NULL; |
276 |
compute->vector = NULL; |
compute->vector = NULL; |
281 |
|
|
282 |
/* Deletes all the fields in COMPUTE. */ |
/* Deletes all the fields in COMPUTE. */ |
283 |
static void |
static void |
284 |
compute_trns_free (struct trns_header *compute_) |
compute_trns_free (void *compute_) |
285 |
{ |
{ |
286 |
struct compute_trns *compute = (struct compute_trns *) compute_; |
struct compute_trns *compute = compute_; |
287 |
|
|
288 |
expr_free (compute->test); |
if (compute != NULL) |
289 |
expr_free (compute->element); |
{ |
290 |
expr_free (compute->rvalue); |
expr_free (compute->test); |
291 |
|
expr_free (compute->element); |
292 |
|
expr_free (compute->rvalue); |
293 |
|
free (compute); |
294 |
|
} |
295 |
} |
} |
296 |
|
|
297 |
/* COMPUTE or IF target variable or vector element. */ |
/* COMPUTE or IF target variable or vector element. */ |
368 |
} |
} |
369 |
|
|
370 |
/* Returns nonzero if LVALUE has a vector as its target. */ |
/* Returns nonzero if LVALUE has a vector as its target. */ |
371 |
static int |
static bool |
372 |
lvalue_is_vector (const struct lvalue *lvalue) |
lvalue_is_vector (const struct lvalue *lvalue) |
373 |
{ |
{ |
374 |
return lvalue->vector != NULL; |
return lvalue->vector != NULL; |
377 |
/* Finalizes making LVALUE the target of COMPUTE, by creating the |
/* Finalizes making LVALUE the target of COMPUTE, by creating the |
378 |
target variable if necessary and setting fields in COMPUTE. */ |
target variable if necessary and setting fields in COMPUTE. */ |
379 |
static void |
static void |
380 |
lvalue_finalize (struct lvalue *lvalue, |
lvalue_finalize (struct lvalue *lvalue, struct compute_trns *compute) |
|
struct compute_trns *compute) |
|
381 |
{ |
{ |
382 |
if (lvalue->vector == NULL) |
if (lvalue->vector == NULL) |
383 |
{ |
{ |
407 |
static void |
static void |
408 |
lvalue_destroy (struct lvalue *lvalue) |
lvalue_destroy (struct lvalue *lvalue) |
409 |
{ |
{ |
410 |
if ( ! lvalue ) |
if (lvalue == NULL) |
411 |
return ; |
return; |
412 |
|
|
413 |
expr_free (lvalue->element); |
expr_free (lvalue->element); |
414 |
free (lvalue); |
free (lvalue); |